2009-04-08 33 views
6

Tengo una tabla de eventos que especifica un rango de fechas con los campos start_date y end_date. Tengo otro rango de fechas, especificado en el código, que define la semana actual como 'week_start' y 'week_end'.¿Cómo determinar si un rango de fechas ocurre en cualquier momento dentro de otro rango de fechas?

Me gustaría consultar todos los eventos de la semana. Los casos parecen ser: comienza

  • Evento y termina dentro de la semana
  • Evento comienza antes de la semana, pero termina dentro de la semana comienza
  • de eventos dentro de la semana, pero termina después de la semana
  • evento comienza antes de la semana y también termina después de la semana
  • Eventos que ni residir dentro, ni superponerse a la semana en todos se ignoran

Estoy intentando encontrar una consulta que pueda manejar todos estos casos. Hasta ahora solo he podido obtener casos que manejan superposiciones semanales o eventos que son completamente internos; Esencialmente, demasiados registros, o ninguno en absoluto.

+0

Este es un duplicado de http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap que tiene una derivación rigurosa de la solución simple (solo 2 condiciones). –

Respuesta

21
(event.start BETWEEN week.start AND week.end) 
OR 
(week.start BETWEEN event.start AND event.end) 

En palabras simples, o una semana comienza durante el evento, o un evento comienza durante la semana.

Vamos a comprobarlo: comienza

Evento y termina dentro de la semana

El evento se inicia durante la semana.

Evento comienza antes de la semana, pero termina dentro de la semana

La semana comienza durante el evento.

evento comienza dentro de la semana, pero termina después de la semana

El evento se inicia durante la semana.

Evento comienza antes de la semana y también termina después de la semana

La semana comienza durante el evento.

Tenga en cuenta que BETWEEN en las expresiones anteriores se utiliza solo en aras de la brevedad.

expresión estricto es el siguiente:

(event.start >= week.start AND event.start < week.end) 
OR 
(week.start >= event.start AND week.start < event.end) 

, siempre que week.end es una week.start + INTERVAL 7 DAY.

I. e. si usted comienzo para la semana de Sun, 0:00:00, entonces debería terminar en next Sun, 0:00:00 (no en Sat, 0:00:00)

Esta expresión parece más compleja que la que se utiliza comúnmente:

event.start < week.end AND event.end > week.start 

, pero el primero es más eficiente y índice amigable.

ver a estos artículos en mi blog para las comparaciones de rendimiento:

+1

Entre aquí es solo por brevedad. Como regla, el fin de semana debería ser un estricto menos. – Quassnoi

+0

Lástima que esto no resolverá el problema de los eventos que comienzan antes de la semana y terminan después de la semana. –

+0

@Pop Catalin: ¿De verdad? ¿La semana en cuestión no comienza durante el evento? – Quassnoi

3

Se puede escribir su condición como esto:

start_date <= week_end AND end_date >= week_start 

Editar: esto supone fecha_inicial < = fecha_final y week_start < = week_end (debidamente ordenada) y le da el mejor rendimiento en la mayoría de las implementaciones db debido a no utilizar O (que en algunas bases de datos pueden crear problemas de rendimiento)

Edit2 : esta solución también resuelve el problema de los eventos que comienzan antes del intervalo y finalizan después del intervalo.

+1

Solución mucho más agradable que entre para la comparación de intervalo –

0

Con el fin ...

where start_date >= week_start and end_date <= week_end 
where start_date <= week_start and end_date >= week_start and end_date <= week_end 
where start_date >= week_start and start_date <= week_end and end_date > week_end 
where start_date < week_start and end_date > week_end 
0

(end2> = start1) & & (start2 < = END1) Creo que volvería cierto para cualquier rango de fechas que se cruzan.

Encontré una discusión sobre esto here que encontré útil.

2

+1 por pop Catalin, pero alas no tengo derecho de voto.

La condición de restricción que desea es solo la forma estándar de expresar el operador "OVERLAPS" de Allen.

advertencia adicional de SQL: if end_date es anulable, asegúrese de tratar nulos en esas columnas como "el final de los tiempos".

Advertencia funcional adicional: asegúrese de adaptar el uso de '< =' versus '<' a si los períodos de tiempo registrados incluyen la fecha de finalización o no.

Cuestiones relacionadas