J'ai une requête comme celle-ci:
SELECT * FROM Cases WHERE created_at BETWEEN '2013-05-01' AND '2013-05-01'
Mais cela ne donne aucun résultat même s'il y a des données sur le 1er.
created_at
ressemble à 2013-05-01 22:25:19
, je suppose que cela a à voir avec le temps? Comment cela pourrait-il être résolu?
Cela fonctionne très bien si je fais de plus grandes plages de dates, mais cela devrait également fonctionner avec une seule date.
Il est inclusif. Vous comparez les dates/heures. La deuxième date est interprétée comme minuit quand le jour commence.
Une façon de résoudre ce problème est:
SELECT *
FROM Cases
WHERE cast(created_at as date) BETWEEN '2013-05-01' AND '2013-05-01'
Une autre façon de résoudre le problème est d'utiliser des comparaisons binaires explicites.
SELECT *
FROM Cases
WHERE created_at >= '2013-05-01' AND created_at < '2013-05-02'
Aaron Bertrand a une longue entrée de blog sur les dates ( ici ), où il discute de cette question et d’autres questions relatives aux dates.
Il a été supposé que la seconde référence de date dans la syntaxe BETWEEN
est considérée comme par magie comme étant la "fin de journée" mais c'est faux .
c'est-à-dire que c'était prévu:
SELECT * FROM Cases WHERE created_at BETWEEN le début de '2013-05-01' ET la fin de '2013-05-01'
mais ce qui se passe réellement est le suivant:
SELECT * FROM Cases WHERE created_at ENTRE '2013-05-01 00: 00: 00 + 00000'AND' 2013-05-01 00: 00: 00 + 00000'
Ce qui devient l'équivalent de:
SELECT * FROM Cas WHERE created_at = '2013-05-01 00: 00: 00 + 00000'
Le problème est celui des perceptions/attentes à propos de BETWEEN
qui inclut inclut à la fois la valeur inférieure et les valeurs supérieures dans la plage, mais ne fait pas comme par magie une date le "début" ou "la fin de ".
BETWEEN
doit être évité lors du filtrage par plages de dates.
Toujours utilise plutôt le >= AND <
SELECT * FROM Cases WHERE (created_at > = '20130501' ET créé à < '20130502')
les parenthèses sont facultatives ici mais peuvent être importantes dans les requêtes plus complexes.
Vous devez faire l'une de ces deux options:
between
: ... where created_at between '2013-05-01 00:00:00' and '2013-05-01 23:59:59'
(non recommandé ... voir le dernier paragraphe)between
. Notez que vous devrez ensuite ajouter un jour à la seconde valeur: ... where (created_at >= '2013-05-01' and created_at < '2013-05-02')
Ma préférence personnelle est la deuxième option. En outre, Aaron Bertrand a une explication très claire pourquoi il devrait être utilisé.
Je trouve que la meilleure solution pour comparer un champ date/heure à un champ date est la suivante:
DECLARE @StartDate DATE = '5/1/2013',
@EndDate DATE = '5/1/2013'
SELECT *
FROM cases
WHERE Datediff(day, created_at, @StartDate) <= 0
AND Datediff(day, created_at, @EndDate) >= 0
Cela équivaut à une instruction inclusive, car elle inclut à la fois les dates de début et de fin, ainsi que celles comprises entre.
Il suffit d'utiliser l'horodatage comme date:
SELECT * FROM Cases WHERE date(created_at)='2013-05-01'
cast(created_at as date)
Cela ne fonctionnera qu'en 2008 et les versions plus récentes de SQL Server
Si vous utilisez une version plus ancienne, utilisez
convert(varchar, created_at, 101)
Vous pouvez utiliser la fonction date()
qui extraira la date d'un datetime et vous donnera le résultat comme date inclusive:
SELECT * FROM Cases WHERE date(created_at)='2013-05-01' AND '2013-05-01'