web-dev-qa-db-fra.com

MySQL "entre" clause non incluse?

Si j'exécute une requête avec une clause between, elle semble exclure la valeur finale.
Par exemple:

select * from person where dob between '2011-01-01' and '2011-01-31'

Cela donne tous les résultats avec dob du '2011-01-01' au '2011-01-30'; ignorer des enregistrements où dob est '2011-01-31'. Quelqu'un peut-il expliquer pourquoi cette requête se comporte de cette manière et comment je pourrais la modifier pour inclure des enregistrements dans lesquels dob est '2011-01-31'? (sans ajouter 1 à la date de fin car il a été sélectionné par les utilisateurs.)

126
ASD

Le champ dob a probablement une composante heure.

Pour le tronquer:

select * from person 
where CAST(dob AS DATE) between '2011-01-01' and '2011-01-31'
155
tiago2014

Depuis le MySQL-manual :

Ceci est équivalent à l'expression (min <= expr AND expr <= max) 

269
Frank Heikens

Le problème est que 2011-01-31 est vraiment 2011-01-31 00:00:00. C'est le début de la journée. Tout pendant la journée n'est pas inclus.

86
Daniel Hilgarth
select * from person where dob between '2011-01-01 00:00:00' and '2011-01-31 23:59:59'
28
Gaurav

Le champ que vous référencez dans votre requête est-il un type Date ou un type - DateTime ?

Une cause fréquente du comportement que vous décrivez est lorsque vous utilisez un type DateTime où vous devriez réellement utiliser un type Date. Autrement dit, à moins que vous ayez vraiment besoin de savoir à quelle heure une personne est née, utilisez simplement le type Date.

La raison pour laquelle le dernier jour n'est pas inclus dans vos résultats est due au fait que la requête utilise la partie heure des dates que vous n'avez pas spécifiée dans votre requête. 

Autrement dit: votre requête est interprétée jusqu'à minuit entre le 30/01/2011 et le 31/01/2011, mais les données peuvent avoir une valeur un peu plus tard dans la journée le 30/01/2011.

Suggestion: remplacez le champ par le type Date s'il s'agit d'un type DateTime.

5
JohnFx

Bonjour cette requête fonctionne pour moi,

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'
4
infinito84
select * from person where DATE(dob) between '2011-01-01' and '2011-01-31'

Étonnamment, de telles conversions sont des solutions à de nombreux problèmes dans MySQL.

2
betty.88

Vous pouvez exécuter la requête en tant que:

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

comme d'autres l'ont fait remarquer, si vos dates sont codées en dur.

Par contre, si la date est dans une autre table, vous pouvez ajouter un jour et en soustraire une seconde (si les dates sont enregistrées sans la seconde/heure), comme ceci:

select * from person JOIN some_table ... where dob between some_table.initial_date and (some_table.final_date + INTERVAL 1 DAY - INTERVAL 1 SECOND)

Évitez les conversions sur les variables dob (comme dans la réponse acceptée), car cela peut entraîner d’énormes problèmes de performances (par exemple, ne pas pouvoir utiliser un index dans le champ dob, en supposant qu’il en existe un). Le plan d'exécution peut passer de using index condition à using where si vous créez quelque chose comme DATE(dob) ou CAST(dob AS DATE), soyez donc prudent!

0
Lucas Basquerotto

Définissez la date supérieure sur + 1 jour. Dans votre cas, définissez-la sur 2011-02-01.

0
Rafal