当日のタイムスタンプを持つ行を選択するにはどうすればよいですか?


104

データベーステーブルから今日のレコードのみを選択しようとしています。

現在使用しています

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

しかし、これには過去24時間の結果が必要です。時間を無視して、今日の結果のみを選択する必要があります。日付のみに基づいて結果を選択するにはどうすればよいですか?

回答:


191

使用DATEしてCURDATE()

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

DATE まだINDEXを使用していると思います。

デモで実行計画を見る


違いを確認してください:SQL-Fiddle 2番目のクエリのFILTERED = 25に注目してください。
ypercubeᵀᴹ

@ypercubeああ、私はそれを逃しましたが、なぜエクストラの価値があるのか​​と思っていましたかUsing where; Using index
John Woo、

1
インデックスは行の選択に使用されます。ただし、クエリ全体でインデックス全体がスキャンされ(条件を評価するためにすべての値がDATE()で変換されます)ます。より良い例で答えを更新します。
ypercubeᵀᴹ

1
ypercubeソリューションは、すべての点を考慮して、パフォーマンス上の理由から優れています。テーブルに数十万行ある場合は、必ずこの方向に進んでください
Vincent

1
「」は重要ですtimestampdate私の場合と同様)はMySQLの予約語です
Victor Ferreira

55

インデックスを使用し、クエリでテーブルスキャンを実行しない場合:

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

これが実際の実行計画にもたらす違いを示すために、SQL-Fiddle(非常に役立つサイト)でテストします。

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') ;

では、2つのバージョンを試してみましょう。


バージョン1 DATE(timestamp) = ?

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

説明:

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

ROWS  FILTERED  EXTRA
6671  100       Using where; Using filesort

それは、すべての(6671)の行をフィルタリングして、(返される行が少ないなどの問題ではありません)filesortレコードを行います


バージョン2 timestamp <= ? AND timestamp < ?

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

説明:

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

インデックス範囲スキャンを使用し、対応する行のみをテーブルから読み取ります。


素晴らしい説明とsql-fiddleに感謝します。一瞬のために私を投げたあなたのスキーマの1つのコメントは、それはINDEX t_IX (timestamp, id)(はず?)だけで可能性がありINDEX t_IX (timestamp)、主キーがインデックスに暗示されるように、。それとも理解できない理由はありますか?私はsql-fiddleで試してみましたが、同じ(より良い)実行プランを見ました
natbro

1
@natbroはい、テーブルがInnoDBエンジンを使用している場合、id(それはPKであり、したがってテーブルのクラスター化インデックスであるため)いずれにしてもインデックスに追加されます。そのため、明示的に追加しても問題ありません(また、オプティマイザの盲点を見つける可能性があります)。このケース/クエリには、確かに関係ありません。
ypercubeᵀᴹ

誰もがなぜtimestamp < CURDATE() + INTERVAL 1 DAY必要なのか説明できますか?
Nightwolf

@Nightwolfは、タイムスタンプ値が将来の場所に行が格納される可能性があるためです。質問は「今日の記録のみ」を要求します。
ypercubeᵀᴹ

@TypoCubeᵀᴹああ、それは純粋にタイムスタンプが将来の日付を行わないためとは考えていませんでした。それでも、覚えておくと良い点があります。
Nightwolf

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

短く、「ANDタイムスタンプ<CURDATE()+間隔1日」を使用する必要はありません。

CURDATE()は常に現在の日付を返すため

MySQL CURDATE()関数


a)質問は「今日のレコードのみ」を要求し、コードは将来の日付も取得します。b)比較が機能しない場合は、DATE(timestamp)を使用して実行する必要があります。つまり、回答を修正すると、@ JohnWooの元の回答が得られます。
カタポファティコ

2

この猫の皮をむく方法はいくつありますか?ここにさらに別のバリアントがあります。

SELECT * FROM tableWHERE DATE(FROM_UNIXTIME(timestamp))= '2015-11-18';


2

特定の日付と比較したい場合は、次のように直接記述できます。

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

//ここで、タイムスタンプはタイプがタイムスタンプである列の名前です

または

今日の日付を取得するために、CURDATE()関数を使用できるため、次のようになります。

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

1

それを日付にキャストするだけです:

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



0

Visual Studio 2017では、組み込みデータベースを開発に使用していると、現在の特定のソリューションで問題が発生し、DATE()が組み込み関数ではないというエラーが発生したため、コードを変更して機能させる必要がありました。

これが私の解決策です:

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


MySQLを使用していない可能性がありますが、他のDBMS(SQL Server)を使用している可能性があります。質問のタグに注意してください。
ypercubeᵀᴹ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.