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
.)