Geçerli günün zaman damgası olan satırlar nasıl seçilir?


105

Bir veritabanı tablosundan sadece bugünün kayıtlarını seçmeye çalışıyorum.

Şu anda kullanıyorum

SELECT * FROM `table` WHERE (`timestamp` > DATE_SUB(now(), INTERVAL 1 DAY));

Ancak bu, son 24 saatin sonuçlarını alıyor ve sadece bugünün sonuçlarını seçmem gerekiyor, zamanı göz ardı ederek. Sonuçları yalnızca tarihe göre nasıl seçebilirim?

Yanıtlar:


193

kullan DATEveCURDATE()

SELECT * FROM `table` WHERE DATE(`timestamp`) = CURDATE()

Sanırım kullanmak DATE hala INDEX kullanıyor .

DEMO'daki uygulama planına bakın


Farkı görün: SQL-Fiddle 2. sorguda FİLTRELİ = 25 olduğuna dikkat edin.
ypercubeᵀᴹ

@ypercube oh bunu kaçırdım ama neden ekstra değerin olduğunu merak ediyordum Using where; Using index?
John Woo

1
Dizin, satırları seçmek için kullanılır. Ancak tüm dizin taranır (ve koşulu değerlendirmek için tüm değerler DATE () ile dönüştürülür) sorgunuzla. Cevabımı daha iyi bir örnekle güncelleyeceğim.
ypercubeᵀᴹ

1
Tüm saygımla, ypercube çözümü performans nedenleriyle daha iyidir, eğer masanızda yüz binlerce satır varsa, kesinlikle bu yöne gitmelisiniz
Vincent

1
`` önemli çünkü timestamp(ve datebenim durumumda olduğu gibi) MySQL için ayrılmış bir kelime
Victor Ferreira

58

Bir dizinin kullanılmasını ve sorgunun tablo taraması yapmamasını istiyorsanız:

WHERE timestamp >= CURDATE()
  AND timestamp < CURDATE() + INTERVAL 1 DAY

Bunun gerçek yürütme planlarında yarattığı farkı göstermek için bir SQL-Fiddle (son derece yararlı bir site) ile test edeceğiz :

CREATE TABLE test                            --- simple table
    ( id INT NOT NULL AUTO_INCREMENT
    ,`timestamp` datetime                    --- index timestamp
    , data VARCHAR(100) NOT NULL 
          DEFAULT 'Sample data'
    , PRIMARY KEY (id)
    , INDEX t_IX (`timestamp`, id)
    ) ;

INSERT INTO test
    (`timestamp`)
VALUES
    ('2013-02-08 00:01:12'),
    ---                                      --- insert about 7k rows
    ('2013-02-08 20:01:12') ;

Şimdi 2 versiyonu deneyelim.


Sürüm 1 ile DATE(timestamp) = ?

EXPLAIN
SELECT * FROM test 
WHERE DATE(timestamp) = CURDATE()            ---  using DATE(timestamp)
ORDER BY timestamp ;

Açıklamak:

ID  SELECT_TYPE  TABLE  TYPE  POSSIBLE_KEYS  KEY  KEY_LEN  REF 
1   SIMPLE       test   ALL

ROWS  FILTERED  EXTRA
6671  100       Using where; Using filesort

O bütün (6671) satırlara filtre ve daha sonra bir filesort (döndürülen satırları birkaçıdır olarak bu bir sorun değil) yapar


Sürüm 2 ile timestamp <= ? AND timestamp < ?

EXPLAIN
SELECT * FROM test 
WHERE timestamp >= CURDATE()
  AND timestamp < CURDATE() + INTERVAL 1 DAY
ORDER BY timestamp ;

Açıklamak:

ID  SELECT_TYPE  TABLE  TYPE  POSSIBLE_KEYS  KEY  KEY_LEN  REF 
1   SIMPLE       test   range t_IX           t_IX    9 

ROWS  FILTERED  EXTRA
2     100       Using where

Dizinde bir aralık taraması kullanır ve ardından tablodan yalnızca karşılık gelen satırları okur.


harika bir açıklama ve sql-fiddle için teşekkürler. Şemanızla ilgili beni bir an için fırlatan bir yorum, bu INDEX t_IX (timestamp, id)sadece olabilir (olmalı mı?) INDEX t_IX (timestamp), çünkü birincil anahtar dizinde belirtilmiştir. yoksa bunu yapmamın bir sebebi var mı? Bunu sql-
fiddle'da

1
@natbro Evet, tablo InnoDB motorunu kullanıyorsa, id(çünkü bu PK ve dolayısıyla tablonun kümelenmiş dizini) yine de dizine eklenir. Dolayısıyla, onu açıkça eklemekten zarar gelmez (ve bazı optimize edici kör noktaları yakalayabilir). Bu durum / sorgu ile kesinlikle alakalı değil.
ypercubeᵀᴹ

Biri neden timestamp < CURDATE() + INTERVAL 1 DAYgerekli olduğunu açıklayabilir mi?
Nightwolf

@Nightwolf, çünkü gelecekte zaman damgası değerinin olduğu yerde depolanan satırlarınız olabilir. Soru "sadece bugünün kayıtları" soruyor .
ypercubeᵀᴹ

@ TypoCubeᵀᴹ Aha, bunu sadece düşünmedim çünkü zaman damgası gelecekteki tarihler için geçerli olmayacak. Yine de akılda tutulması gereken iyi bir nokta.
Nightwolf

12
SELECT * FROM `table` WHERE timestamp >= CURDATE()

daha kısadır, 'AND timestamp <CURDATE () + INTERVAL 1 DAY' kullanımına gerek yoktur

çünkü CURDATE () her zaman geçerli günü döndürür

MySQL CURDATE () Fonksiyonu


1
a) Soru "yalnızca bugünün kayıtlarını" sorar ve kodunuz da gelecekteki tarihleri ​​alır. b) Karşılaştırmanız işe yaramıyor, bunu DATE (zaman damgası) ile yapmalısınız. Başka bir deyişle: Cevabınızı düzeltirseniz, @JohnWoo orijinal cevabını alacaksınız.
Katapofatico

3

Bu kediyi kaç şekilde yüzebiliriz? İşte başka bir varyant.

SEÇİN * tableTARİH (FROM_UNIXTIME ( timestamp)) = '2015-11-18';


3

Belirli bir tarihle karşılaştırmak istiyorsanız, bunu doğrudan şöyle yazabilirsiniz:

select * from `table_name` where timestamp >= '2018-07-07';

// buradaki zaman damgası, zaman damgası olarak türe sahip sütunun adıdır

veya

Bugün tarihini getirmek için CURDATE () işlevi kullanılabilir, bu nedenle:

select * from `table_name` where timestamp >=  CURDATE();

2

Basitçe bir tarihe yayınlayın:

SELECT * FROM `table` WHERE CAST(`timestamp` TO DATE) == CAST(NOW() TO DATE)

2

Bence bu en kolayı olabilir:

SELECT * FROM `table` WHERE `timestamp` like concat(CURDATE(),'%');


1

Visual Studio 2017'de, geliştirme için yerleşik veritabanını kullanarak, mevcut verilen çözümle ilgili sorunlar yaşadım, DATE () 'nin yerleşik bir işlev olmadığı hatasını attığı için kodu değiştirmek zorunda kaldım.

İşte benim çözümüm:

where CAST(TimeCalled AS DATE) = CAST(GETDATE() AS DATE)


Muhtemelen MySQL kullanmıyordunuz ama başka bir DBMS kullanıyordunuz (belki SQL Server?) Sorunun etiketlerine dikkat edin.
ypercubeᵀᴹ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.