sql >> Base de Datos >  >> RDS >> Mysql

Consulta MySQL para cierto rango de fechas

Es sorprendente que nadie se haya dado cuenta de esto durante casi dos años, pero las otras respuestas están todas equivocadas porque no tuvieron en cuenta el caso en que tanto la fecha de inicio como la fecha de finalización caen fuera del alcance del rango de búsqueda. Considere que este es el rango de la fecha:

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

Y este es el rango de nuestra búsqueda:

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

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

La búsqueda debería darnos un resultado positivo porque se cruzan. Pero si usa las otras respuestas, obtendrá un resultado negativo porque ni start_date ni end_date está entre start_search y end_search .

Para obtener la solución, dibujemos los 4 modos posibles de intersección:

                  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

Puedes OR los 4 casos posibles para obtener la solución directa:

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 */

Una solución menos sencilla es:

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 */

Intenta visualizarlo usando los diagramas de arriba.

Si intentamos extrapolar un patrón de los 4 diagramas anteriores, podemos ver que durante una intersección, end_date siempre es >= start_search , y por el otro lado, start_date siempre es <= end_search . De hecho, visualizando más, podemos ver que cuando se cumplen esas dos condiciones, no podemos no tener una intersección .

Como tal, otra solución es tan simple como:

select*from table where

end_date >= start_search && start_date <= end_search

Y la ventaja de esta solución es que solo necesitamos 2 comparaciones. Contraste eso con "OR "todo" que requiere desde 2 hasta 8 (3 + 3 + 2) comparaciones. (Cada between la llamada consta de 3 comparaciones .)