MySQL SELECT WHERE datetime correspond au jour (et pas nécessairement à l'heure)

127

J'ai une table qui contient une colonne datetime. Je souhaite retourner tous les enregistrements d'un jour donné quelle que soit l'heure. Ou en d'autres termes, si ma table ne contenait que les 4 enregistrements suivants, seuls les 2ème et 3ème seraient retournés si je limite au 2012-12-25.

2012-12-24 00:00:00
2012-12-25 00:00:00
2012-12-25 06:00:00
2012-12-26 05:00:00
utilisateur1032531
la source
Voir la réponse de John Woo sur stackoverflow.com/questions/14769026/…
ekerner

Réponses:

326

N'utilisez JAMAIS un sélecteur comme DATE(datecolumns) = '2012-12-24'- c'est un tueur de performances:

  • 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

C'est beaucoup plus rapide à utiliser

SELECT * FROM tablename 
WHERE columname BETWEEN '2012-12-25 00:00:00' AND '2012-12-25 23:59:59'

car cela permettra l'utilisation de l'indice sans calcul.

ÉDITER

Comme l'a souligné Used_By_Already, depuis la réponse initiale en 2012, il y a eu des versions de MySQL, où l'utilisation de «23: 59: 59» comme fin de journée n'est plus sûre. Une version mise à jour devrait lire

SELECT * FROM tablename 
WHERE columname >='2012-12-25 00:00:00'
AND columname <'2012-12-26 00:00:00'

L'essentiel de la réponse, c'est-à-dire l'évitement d'un sélecteur sur une expression calculée, tient bien sûr toujours.

Eugen Rieck
la source
J'étais sur le point de commenter que la solution d'a1ex07 ne semble pas aussi bonne que les autres. Après avoir lu votre message, je dois peut-être inverser ma pensée!
user1032531
2
Juste testé sur deux serveurs, ce qui précède est BEAUCOUP (10x au moins) plus rapide que date () = '' en particulier pour les tables énormes. Merci
zzapper
1
@KonradViltersten J'ai utilisé une façon très verbeuse de formuler la requête pour la rendre plus lisible et faire ressortir mon point, sans l'affiner. La réponse par a1ex07 a la syntaxe creuse.
Eugen Rieck
9
@KonradViltersten - Mieux encore: WHERE col >= '2012-12-25' AND col < '2012-12-25' + INTERVAL 1 DAY. Il évite 0 temps et travaille pour DATE, DATETIME, DATETIME(6), etc. Et traite bissextile jours, etc.
Rick James
1
'2012-12-25 23:59:59' n'est PAS VALIDE comme une fin de journée, c'était toujours une mauvaise idée et cela causera des bogues pour les versions de MySQL qui supportent une précision temporelle inférieure à la seconde. Mieux vaut utiliser l'approche de Rick James (ci-dessus) ou a1ex07 (autre réponse)
Used_By_Already
34

... WHERE date_column >='2012-12-25' AND date_column <'2012-12-26'peut potentiellement mieux fonctionner (si vous avez un index sur date_column) que DATE.

a1ex07
la source
1
Je me demande en fait ce qui est le plus rapide - telle ou telle BETWEENsolution ...
jave.web
6
Cela ne devrait pas faire de différence. BETWEENest juste une manière d'écrire field >= value1 and fied<= value2.
a1ex07
1
Notez que selon le manuel MySQL: "Pour de meilleurs résultats lorsque vous utilisez BETWEEN avec des valeurs de date ou d'heure, utilisez CAST () pour convertir explicitement les valeurs dans le type de données souhaité. Exemples: Si vous comparez un DATETIME à deux valeurs DATE, convertissez le DATE valeurs en valeurs DATETIME. Si vous utilisez une constante de chaîne telle que "2001-1-1" dans une comparaison avec un DATE, transtypez la chaîne en DATE. " Donc, à moins qu'ils ne soient tous du même type, il est préférable de les lancer explicitement.
techdude
21

Vous pouvez utiliser %:

SELECT * FROM datetable WHERE datecol LIKE '2012-12-25%'
Ghilas BELHADJ
la source
13
LIKE semble être aussi lent que DATE (datetimecol). Mieux vaut utiliser la solution d'Eugen ou d'a1ex07.
Marie Fischer
3
Ce n'est pas toujours une question de vitesse. Alors j'aime cette solution. C'est beaucoup plus lisible.
Simon Hansen