Wie wähle ich das Datum aus der Spalte Datum / Uhrzeit aus?

238

Ich habe eine Spalte vom Typ "datetime" mit Werten wie 2009-10-20 10:00:00

Ich möchte Datum aus Datum / Uhrzeit extrahieren und eine Abfrage schreiben wie:

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

Ist das Folgende der beste Weg, dies zu tun?

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

Dies gibt jedoch eine leere Ergebnismenge zurück. Irgendwelche Vorschläge?

mysqllearner
quelle

Antworten:

455

Sie können die MySQL- DATE()Funktion verwenden:

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

Sie können dies auch versuchen:

WHERE datetime LIKE '2009-10-20%'

In dieser Antwort finden Sie Informationen zu den Auswirkungen der Verwendung auf die Leistung LIKE.

Priyank Bolia
quelle
2
versuchte dies: Wo DATE (datetime) = '2009-10-20', funktioniert es
mysqllearner
44
Der erste ist sehr langsam und ignoriert die Indizes. Es ist besser, LIKE 'Datum%' zu haben
Kachar
WHERE DATE (datetime) LIKE '% keyword%' funktioniert, danke
silvia zulinka
2
Ich glaube, dass dies nicht wie erwartet funktioniert, wenn die Rails-Zeitzone etwas anderes als UTC ist. Dies liegt daran, dass DATE () den Spaltenwert in UTC auflöst. Ein Datum wie "Fr, 30 Dec 2016 00:00:00 SGT +08: 00", das wir voraussichtlich finden, wenn wir nach "2016-12-30" fragen, wird daher nicht gefunden. Warum? Weil DATE () es vor dem Vergleich in sein UTC-Äquivalent auflöst, das "2016-12-29 16:00:00 UTC" ist. Korrigieren Sie mich, wenn ich falsch liege, da dies bis vor kurzem auch ein Problem für mich war.
Tikiboy
WHERE DATE (datetime) = '{? Sdate} funktioniert perfekt für einen Crystal Reports-Parameter! Gute Arbeit!
MikeMighty
94

Die Verwendung WHERE DATE(datetime) = '2009-10-20' hat Leistungsprobleme . Wie hier angegeben :

  • Es wird DATE()für alle Zeilen berechnet , auch für diejenigen, die nicht übereinstimmen.
  • Dadurch wird es unmöglich, einen Index für die Abfrage zu verwenden.

Verwenden Sie BETWEENoder >, <, =Operatoren , die erlauben , einen Index zu verwenden:

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

Update: Die Auswirkungen auf die Verwendung LIKEvon Operatoren anstelle von Operatoren in einer indizierten Spalte sind hoch . Dies sind einige Testergebnisse für eine Tabelle mit 1.176.000 Zeilen:

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

Bei einem zweiten Aufruf über dieselbe Abfrage ist der Unterschied sogar noch größer: 2984 ms gegenüber 7 ms (ja, nur 7 Millisekunden!). Ich habe dies gefunden, als ich alten Code für ein Projekt mit Hibernate neu geschrieben habe.

IvanRF
quelle
Interessant, wenn die MySQL-Implementierung automatisch konvertiert DATE(datetime), BETWEEN AND um die Szenen zu betrachten, erhalten wir eine kurze Aussage und eine coole Leistung. Warum nicht? Warum haben sie das nicht getan? :)
Cherry
Weil so etwas DATE(datetime) in (:list)nicht funktioniertBETWEEN
Tim
25

Sie können die Datums- und Uhrzeitangabe auf den YMD-Teil formatieren:

DATE_FORMAT(datetime, '%Y-%m-%d')
Prusprus
quelle
2
Und auf diese Weise können Sie nur den DATE_FORMAT(datetime, '%H:%i:%S')
Zeitteil erhalten,
Dies funktioniert hervorragend beim Formatieren der Datums- und Uhrzeitangabe, aber im Gegenzug gibt die Datenbank ein neues Array zurück, um den Namen dafür festzulegen. Fügen Sie am Ende einfach den gewünschten Namen hinzu. DATE_FORMAT (Spaltenname, '% Y-% m-% d') Arrayname für weitere Details Dokumentationen dev.mysql.com/doc/refman/8.0/en/…
Ridha Rezzag
15

Obwohl alle Antworten auf der Seite das gewünschte Ergebnis liefern, weisen alle Leistungsprobleme auf. Führen Sie niemals Berechnungen für Felder in der WHEREKlausel (einschließlich einer DATE()Berechnung) durch, da diese Berechnung für alle Zeilen in der Tabelle durchgeführt werden muss.

Das BETWEEN ... ANDKonstrukt ist für beide Randbedingungen inklusive und erfordert, dass die Syntax 23:59:59 am Enddatum angegeben wird, die selbst andere Probleme aufweist (Mikrosekunden-Transaktionen, die MySQL meiner Meinung nach 2009 nicht unterstützt hat, als die Frage gestellt wurde).

Die richtige Methode zum Abfragen eines MySQL- timestampFelds für einen bestimmten Tag besteht darin, nach Größer als Gleich am gewünschten Datum und nach Weniger als am Tag danach zu suchen, ohne dass eine Stunde angegeben ist.

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

Dies ist die Methode mit der schnellsten Leistung, dem geringsten Arbeitsspeicher und der geringsten Ressourcenintensität und unterstützt zusätzlich alle MySQL-Funktionen und Eckfälle, z. B. die Genauigkeit von Zeitstempeln unter einer Sekunde. Darüber hinaus ist es zukunftssicher.

dotancohen
quelle
1
Und werden unter Verwendung Ihres Leistungsarguments "> =" und "<" in jeder Zeile der Tabelle gleichermaßen berechnet, oder der SQL Server weiß nur "magisch", ob eine Zahl größer als eine andere ist? :-)
Javier Guerrero
@JavierGuerrero: In meinem Beispiel werden zwei Konstanten verglichen: eine aus der Tabelle und ein String-Literal.
Dotancohen
Die "Eins aus der Tabelle" ist keine Konstante, sie variiert für jede Zeile, daher muss für jede Zeile dieselbe Berechnung durchgeführt werden (und außerdem müssen beide in die Epochenzeit konvertiert werden, um den Vergleich durchzuführen)
Javier Guerrero
9

Hier sind alle Formate

Angenommen, dies ist die Spalte, die den datetimeWert table enthält 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 |
+----------------------+
Siraj Alam
quelle
5

Sie können verwenden:

DATEDIFF ( day , startdate , enddate ) = 0

Oder:

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

Oder:

CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))
Michel van Engelen
quelle
5

einfache und beste Möglichkeit, die Datumsfunktion zu verwenden

Beispiel

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

ODER

SELECT * FROM 
data 
WHERE date(datetime ) >=   '2009-10-20'  && date(datetime )  <= '2009-10-20'
Raja Rama Mohan Thavalam
quelle
-5

Die Verwendung der LIKEAnweisung in ist WHERE datetime LIKE '2009-10-20%' in diesem Fall die beste Option

imran
quelle