Comment sélectionner la date dans la colonne datetime?

238

J'ai une colonne de type "datetime" avec des valeurs comme 2009-10-20 10:00:00

Je voudrais extraire la date de datetime et écrire une requête comme:

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

Est-ce que la meilleure façon de procéder est la suivante?

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

Cela renvoie cependant un jeu de résultats vide. Aucune suggestion?

mysqllearner
la source

Réponses:

456

Vous pouvez utiliser la DATE()fonction de MySQL :

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

Vous pouvez également essayer ceci:

WHERE datetime LIKE '2009-10-20%'

Consultez cette réponse pour plus d'informations sur les implications de l'utilisation de la performance LIKE.

Priyank Bolia
la source
2
essayé celui-ci: Où DATE (datetime) = '2009-10-20', cela fonctionne
mysqllearner
44
Le premier est très lent et ignore les index. Il vaut mieux avoir LIKE 'date%'
kachar
OERE LA DATE (datetime) AIME '% keyword%' son fonctionnement, merci
silvia zulinka
2
Je crois que cela ne fonctionne pas comme prévu si le fuseau horaire de Rails est autre que UTC. En effet, DATE () résout la valeur de la colonne en UTC. Par conséquent, une date telle que "ven. 30 déc. 2016 00:00:00 SGT +08: 00" que nous nous attendons à trouver si nous avons demandé "2016-12-30" ne sera pas trouvée. Pourquoi? Parce que DATE () le résoudra en son équivalent UTC avant de faire le comparisme, qui est "2016-12-29 16:00:00 UTC". Corrigez-moi si je me trompe car c'était aussi un problème pour moi jusqu'à récemment.
Tikiboy
WHERE DATE (datetime) = '{? Sdate} fonctionne parfaitement pour un paramètre Crystal Reports! Bon travail!
MikeMighty
94

L'utilisation WHERE DATE(datetime) = '2009-10-20' présente des problèmes de performances . Comme indiqué ici :

  • il calculera DATE()pour toutes les lignes, y compris celles qui ne correspondent pas.
  • cela rendra impossible l'utilisation d'un index pour la requête.

Utilisez BETWEENou >, <, les =opérateurs qui permettent d'utiliser un indice:

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

Mise à jour: l' impact sur l'utilisation LIKEau lieu d'opérateurs dans une colonne indexée est élevé . Voici quelques résultats de test sur une table avec 1 176 000 lignes:

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

Lorsque vous effectuez un deuxième appel sur la même requête, la différence est encore plus élevée: 2984 ms contre 7 ms (oui, seulement 7 millisecondes!). J'ai trouvé cela en réécrivant un ancien code sur un projet utilisant Hibernate.

IvanRF
la source
Intéressant, si l'implémentation de MySql se convertit automatiquement DATE(datetime)pour BETWEEN AND améliorer les scènes, nous obtenons une déclaration courte et des performances intéressantes. Pourquoi pas? Pourquoi ne l'ont-ils pas fait? :)
Cherry
Parce que quelque chose comme ça ne DATE(datetime) in (:list)marche pasBETWEEN
Tim
25

Vous pouvez formater le datetime à la partie YMD:

DATE_FORMAT(datetime, '%Y-%m-%d')
Prusprus
la source
2
Et de cette façon, vous ne pouvez obtenir que la partie de temps si nécessaire:DATE_FORMAT(datetime, '%H:%i:%S')
Metafaniel
cela fonctionne très bien en formatant le datetime mais en retour la base de données renverra un nouveau tableau pour lui attribuer le nom juste le nom souhaité à la fin DATE_FORMAT (columnName, '% Y-% m-% d') arrayName pour plus de détails, vérifiez documentations dev.mysql.com/doc/refman/8.0/en/…
Ridha Rezzag
15

Bien que toutes les réponses sur la page renvoient le résultat souhaité, elles ont toutes des problèmes de performances. N'effectuez jamais de calculs sur les champs de la WHEREclause (y compris un DATE()calcul) car ce calcul doit être effectué sur toutes les lignes du tableau.

La BETWEEN ... ANDconstruction est inclusive pour les deux conditions de frontière, exigeant que l'on spécifie la syntaxe 23:59:59 à la date de fin qui elle-même a d'autres problèmes (transactions en microsecondes, que je crois que MySQL n'a pas pris en charge en 2009 lorsque la question a été posée).

La bonne façon d'interroger un timestampchamp MySQL pour un jour particulier est de vérifier si Supérieur à Egal par rapport à la date souhaitée et Inférieur à jour après, sans heure spécifiée.

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

Il s'agit de la méthode la plus rapide, la moins gourmande en mémoire et la moins gourmande en ressources, et prend également en charge toutes les fonctionnalités MySQL et les cas d'angle tels que la précision d'horodatage en une seconde. De plus, il est à l'épreuve du temps.

dotancohen
la source
1
Et, à l'aide de votre argument de performances, les "> =" et "<" sont-ils calculés de manière égale sur chaque ligne de la table, ou le serveur SQL sait-il "par magie" si un nombre est supérieur aux autres? :-)
Javier Guerrero
@JavierGuerrero: Mon exemple compare deux constantes: une de la table et une chaîne littérale.
dotancohen
Le "un du tableau" n'est pas une constante, il varie pour chaque ligne, donc le même calcul doit être fait pour chaque ligne (et aussi, les deux doivent être convertis en temps d'époque pour effectuer la comparaison)
Javier Guerrero
9

Voici tous les formats

Disons que c'est la colonne qui contient la datetimevaleur, 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 |
+----------------------+
Siraj Alam
la source
5

Vous pouvez utiliser:

DATEDIFF ( day , startdate , enddate ) = 0

Ou:

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

Ou:

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

façon simple et optimale d'utiliser la fonction de date

exemple

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

OU

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

Eh bien, utiliser LIKEdans la déclaration est la meilleure option, WHERE datetime LIKE '2009-10-20%' cela devrait fonctionner dans ce cas

imran
la source