Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Consulta MySQL para determinado intervalo de datas


É incrível que ninguém tenha notado isso por quase dois anos, mas as outras respostas estão todas erradas porque eles não levaram em consideração o caso em que a data de início e a data de término estão além do escopo do intervalo de pesquisa. Considere que este é o intervalo da data:
start_date <<---------------------------- date range --------------------------->> end_date

E este é o alcance da nossa pesquisa:
start_date <<---------------------------- date range --------------------------->> end_date

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

A pesquisa deve nos dar um resultado positivo porque eles se cruzam. Mas se você usar as outras respostas, obterá um resultado negativo porque nem start_date nem end_date está entre start_search e end_search .

Para obter a solução, vamos desenhar todos os 4 modos possíveis de cruzamento:
                  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

Você pode OR todos os 4 casos possíveis para obter a solução direta:
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 */

Uma solução menos direta é:
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 */

Tente visualizá-lo usando os diagramas acima.
Se tentarmos extrapolar um padrão dos 4 diagramas acima, podemos ver que durante uma interseção, end_date é sempre >= start_search , e por outro lado, start_date é sempre <= end_search . De fato, visualizando mais, podemos ver que quando essas duas condições são válidas, não podemos deixar de ter uma interseção .
Como tal, outra solução é tão simples quanto:
select*from table where

end_date >= start_search && start_date <= end_search

E a vantagem desta solução é que só precisamos de 2 comparações. Compare isso com o "OR tudo" que requer de 2 até 8 (3 + 3 + 2) comparações. (Cada between chamada consiste em 3 comparações .)