170 votes

SQL "entre" non inclusif

J'ai une requête de ce type :

SELECT * FROM Cases WHERE created_at BETWEEN '2013-05-01' AND '2013-05-01'

Mais cela ne donne aucun résultat alors qu'il existe des données sur le 1er.

created_at ressemble à 2013-05-01 22:25:19 Je pense que cela a à voir avec l'heure ? Comment résoudre ce problème ?

Cela fonctionne très bien si je fais des plages de dates plus larges, mais cela devrait aussi fonctionner (inclusivement) avec une seule date.

355voto

Gordon Linoff Points 213350

Il est inclusive. Vous comparez des dates à des dates. La deuxième date est interprétée comme minuit quand la journée 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 ce 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 un long article de blog sur les dates ( aquí ), où il aborde cette question et d'autres problèmes de datation.

69voto

Used_By_Already Points 3540

Il a été supposé que la deuxième référence de date dans les BETWEEN la syntaxe est magiquement considérée comme la "fin de la journée" mais c'est faux .

c'est-à-dire que c'était attendu :

SELECT \* FROM Cases 
WHERE created\_at BETWEEN **_the beginning of_** '2013-05-01' AND **_the end of_** '2013-05-01'

mais ce qui se passe réellement est ceci :

SELECT \* FROM Cases 
WHERE created\_at BETWEEN '2013-05-01 **00:00:00+00000**' AND '2013-05-01 **00:00:00+00000**'

Ce qui devient l'équivalent de :

SELECT \* FROM Cases WHERE created\_at **\=** '2013-05-01 **00:00:00+00000**'

Le problème est celui des perceptions et des attentes à l'égard de l'Europe. BETWEEN dont hace inclure à la fois la valeur inférieure et la valeur supérieure de l'intervalle, mais no faire magiquement d'une date le "début de" ou "la fin de".

BETWEEN doivent être évités lors du filtrage par plages de dates.

Toujours utiliser le >= AND < au lieu de

SELECT \* FROM Cases 
WHERE (created\_at **\>=** '20130501' **AND** created\_at **<** '20130502')

les parenthèses sont facultatives ici mais peuvent être importantes dans des requêtes plus complexes.

19voto

Barranka Points 6560

Vous devez choisir l'une de ces deux options :

  1. Incluez la composante temps dans votre between condition : ... where created_at between '2013-05-01 00:00:00' and '2013-05-01 23:59:59' (non recommandé... voir le dernier paragraphe)
  2. Utilisez des inégalités au lieu de between . Remarquez que vous devrez alors ajouter un jour à la deuxième valeur : ... where (created_at >= '2013-05-01' and created_at < '2013-05-02')

Ma préférence personnelle va à la deuxième option. Aussi, Aaron Bertrand tiene une explication très claire de la raison pour laquelle il doit être utilisé.

9voto

Balinti Points 1504

Utilisez simplement l'horodatage comme date :

SELECT * FROM Cases WHERE date(created_at)='2013-05-01'

7voto

Ted Points 71

Je trouve que la meilleure solution pour comparer un champ de date à un champ de 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 déclaration intermédiaire inclusive, car elle inclut à la fois la date de début et la date de fin, ainsi que les dates intermédiaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X