日時列から日付を選択するにはどうすればよいですか?


238

2009-10-20 10:00:00のような値を持つ「datetime」タイプの列があります

datetimeから日付を抽出して、次のようなクエリを記述します。

SELECT * FROM 
data 
WHERE datetime = '2009-10-20' 
ORDER BY datetime DESC

以下はそれを行うための最良の方法ですか?

SELECT * FROM 
data 
WHERE datetime BETWEEN('2009-10-20 00:00:00' AND '2009-10-20 23:59:59')
ORDER BY datetime DESC

ただし、これは空の結果セットを返します。助言がありますか?

回答:


456

MySQLのDATE()関数を使用できます。

WHERE DATE(datetime) = '2009-10-20'

これを試すこともできます:

WHERE datetime LIKE '2009-10-20%'

の使用によるパフォーマンスへの影響については、この回答を参照してくださいLIKE


2
これを試してみました:DATE(datetime)= '2009-10-20'の場合、機能します
mysqllearner '18年

44
最初のものは非常に遅く、インデックスを無視します。LIKE 'date%'を
指定することをお勧めし

WHERE DATE(datetime)LIKE '%keyword%'機能します。ありがとう
シルビアズリンカ

2
RailsのタイムゾーンがUTC以外の場合、これは期待どおりに機能しないと思います。これは、DATE()が列の値をUTCに解決するためです。そのため、「2016年12月30日金曜日00:00:00 SGT +08:00」など、「2016-12-30」を照会した場合に見つかると予想される日付は見つかりません。どうして?なぜなら、DATE()は、比較を行う前に、それをそのUTCの同等物、つまり「2016-12-29 16:00:00 UTC」に解決するためです。これが最近まで私にとっても問題であったので、私が間違っている場合は修正してください。
Tikiboy 2017年

WHERE DATE(datetime)= '{?sdate}は、Crystal Reportsパラメータに対して完全に機能します。よくやった!
MikeMighty 2017

94

使用にWHERE DATE(datetime) = '2009-10-20' はパフォーマンスの問題があります。ここで述べたように

  • DATE()一致しないものも含め、すべての行について計算されます。
  • クエリにインデックスを使用できなくなります。

使用するBETWEEN><=インデックスを使用できるようにする演算子:

SELECT * FROM data 
WHERE datetime BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59'

更新:衝撃使用にLIKE索引付けされた列に代わりにオペレータが高いです。これらは、1,176,000行のテーブルに対するいくつかのテスト結果です。

  • 使用datetime LIKE '2009-10-20%'=> 2931ms
  • datetime >= '2009-10-20 00:00:00' AND datetime <= '2009-10-20 23:59:59'=> 168ms を使用

同じクエリで2回目の呼び出しを行うと、差はさらに大きくなります。2984ms対7ms(はい、わずか7ミリ秒です!)。Hibernateを使用してプロジェクトの古いコードを書き直しているときに、これを見つけました。


興味深いことに、MySql実装がシーンを自動的に変換DATE(datetime)して変換するBETWEEN AND と、短いステートメントとクールなパフォーマンスが得られます。何故なの?なぜ彼らはこれをしなかったのですか?:)
Cherry

のようなものがDATE(datetime) in (:list)機能しないためBETWEEN
Tim

25

日時をYMD部分にフォーマットできます。

DATE_FORMAT(datetime, '%Y-%m-%d')

2
必要な場合にのみ、時間の一部を取得することができ、この方法:DATE_FORMAT(datetime, '%H:%i:%S')
Metafaniel

これは日時の書式設定に最適ですが、データベースは新しい配列を返し、名前を設定します。末尾に目的の名前を追加しますDATE_FORMAT(columnName、 '%Y-%m-%d')arrayName for more details checkドキュメンテーション dev.mysql.com/doc/refman/8.0/en/...
Ridha Rezzag

15

ページ上のすべての回答で目的の結果が返されますが、すべてにパフォーマンスの問題があります。その計算はテーブルのすべての行で実行する必要があるためWHERE句のフィールド(DATE()計算を含む)で計算を実行しないでください。

BETWEEN ... AND構築物は、それ自体が他の問題(私は質問が尋ねられたとき、MySQLは2009年にはサポートしていませんでしたと信じてマイクロ秒の取引を、)は終了日の夜11時59分59秒の構文を指定するために1つを必要とし、双方の境界条件のための包括的です。

timestamp特定の日のMySQL フィールドをクエリする適切な方法は、希望の日付に対してGreater-Than-Equalsをチェックし、時間を指定せずに翌日に対してLess-Thanをチェックすることです。

WHERE datetime>='2009-10-20' AND datetime<'2009-10-21'

これは、パフォーマンスが最も速く、メモリが最も少なく、リソースをほとんど消費しない方法であり、さらにすべてのMySQL機能と、1秒未満のタイムスタンプ精度などの特殊なケースをサポートします。さらに、それは将来の証拠です。


1
そして、パフォーマンス引数を使用して、 "> ="と "<"はテーブルの各行で等しく計算されますか、またはSQLサーバーは数値が他よりも大きいかどうかを "魔法のように"知っていますか?:-)
ハビエルゲレーロ

@JavierGuerrero:私の例では、2つの定数を比較しています。1つはテーブルの定数で、もう1つは文字列リテラルです。
dotancohen 2017年

「テーブルからの1つ」は定数ではなく、行ごとに異なるため、行ごとに同じ計算を行う必要があります(また、比較を実行するには両方をエポック時間に変換する必要があります)
Javier Guerrero

9

ここにすべてのフォーマットがあります

これがdatetime値table を含む列だとしますdata

+--------------------+
| date_created       |
+--------------------+
| 2018-06-02 15:50:30|
+--------------------+

mysql> select DATE(date_created) from data;
+--------------------+
| DATE(date_created) |
+--------------------+
| 2018-06-02         |
+--------------------+

mysql> select YEAR(date_created) from data;
+--------------------+
| YEAR(date_created) |
+--------------------+
|               2018 |
+--------------------+

mysql> select MONTH(date_created) from data;
+---------------------+
| MONTH(date_created) |
+---------------------+
|                   6 |
+---------------------+

mysql> select DAY(date_created) from data;
+-------------------+
| DAY(date_created) |
+-------------------+
|                 2 |
+-------------------+

mysql> select HOUR(date_created) from data;
+--------------------+
| HOUR(date_created) |
+--------------------+
|                 15 |
+--------------------+

mysql> select MINUTE(date_created) from data;
+----------------------+
| MINUTE(date_created) |
+----------------------+
|                   50 |
+----------------------+

mysql> select SECOND(date_created) from data;
+----------------------+
| SECOND(date_created) |
+----------------------+
|                   31 |
+----------------------+

5

以下を使用できます。

DATEDIFF ( day , startdate , enddate ) = 0

または:

DATEPART( day, startdate ) = DATEPART(day, enddate)
AND 
DATEPART( month, startdate ) = DATEPART(month, enddate)
AND
DATEPART( year, startdate ) = DATEPART(year, enddate)

または:

CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))

5

日付関数を使用するためのシンプルで最良の方法

SELECT * FROM 
data 
WHERE date(datetime) = '2009-10-20' 

または

SELECT * FROM 
data 
WHERE date(datetime ) >=   '2009-10-20'  && date(datetime )  <= '2009-10-20'

-5

まあ、LIKEステートメントでの使用は、WHERE datetime LIKE '2009-10-20%' この場合に機能する最良のオプションです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.