Mysql
 sql >> Base de données >  >> RDS >> Mysql

Requête MySQL pour une certaine plage de dates

C'est incroyable que personne ne l'ait remarqué depuis près de deux ans, mais les autres réponses sont toutes fausses parce qu'ils n'ont pas pris en compte le cas où la date de début et la date de fin se situent en dehors de la portée de la plage de recherche. Considérez ceci comme la plage de dates :

start_date <<---------------------------- date range --------------------------->> end_date

Et voici la portée de notre recherche :

start_date <<---------------------------- date range --------------------------->> end_date

                 start_search <<-------- search range -------->> end_search

La recherche devrait nous donner un résultat positif car ils se croisent. Mais si vous utilisez les autres réponses, vous obtiendrez un résultat négatif car ni start_date ni end_date est entre start_search et end_search .

Pour obtenir la solution, dessinons les 4 modes possibles d'intersection :

                  start_date <<---------- date range --------------------------->> end_date

start_search <<------------------------- search range -------->> end_search
start_date <<---------------------------- date range ---------->> end_date

               start_search <<---------- search range ------------------------>> end_search
start_date <<---------------------------- date range --------------------------->> end_date

                 start_search <<-------- search range -------->> end_search
                 start_date <<----------- date range -------->> end_date

start_search <<------------------------- search range ------------------------>> end_search

Vous pouvez OR les 4 cas possibles pour obtenir la solution directe :

select*from table where

   /* 1st case */ start_date between start_search and end_search         
or /* 2nd case */  end_date  between start_search and end_search         
or /* 3rd case */ (start_date <= start_search and end_date >= end_search)
or /* 4th case */ (start_date >= start_search and end_date <= end_search)

/* the 4th case here is actually redundant since it is being covered by the 1st and 2nd cases */

Une solution moins simple est :

select*from table where

    start_date  between start_search and end_search /* covers 1st and 4th cases */          
or start_search between  start_date  and  end_date  /* covers 2nd and 3rd cases */

Essayez de le visualiser à l'aide des schémas ci-dessus.

Si nous essayons d'extrapoler un modèle sur les 4 diagrammes ci-dessus, nous pouvons voir que lors d'une intersection, end_date est toujours >= start_search , et d'un autre côté, start_date est toujours <= end_search . En effet, en visualisant plus loin, nous pouvons voir que lorsque ces deux conditions sont remplies, nous ne pouvons pas ne pas avoir d'intersection .

En tant que tel, une autre solution est aussi simple que :

select*from table where

end_date >= start_search && start_date <= end_search

Et l'avantage de cette solution est que nous n'avons besoin que de 2 comparaisons. Comparez cela avec le "OR tout" qui nécessite de 2 à 8 (3 + 3 + 2) comparaisons. (Chaque between l'appel consiste en 3 comparaisons .)