2009-06-22 18 views
6

Tengo el siguiente conjunto de fechas (dd/mm/aaaa) Eventos en mi base de datos que emparejan:Calcular los intervalos de fechas que faltan y los intervalos de fechas que se solapan entre dos fechas

 
eventId  startDate  endDate 
1   02/05/2009 10/05/2009 
2   08/05/2009 12/05/2009 
3   10/05/2009 12/05/2009 
4   21/05/2009 21/05/2009 
5   25/05/2009 NULL 
6   01/06/2009 03/06/2009 

Los eventos tienen una fecha de inicio y fin (los tiempos no importan) y un NULL endDate significa que el evento aún está en progreso.

Lo que me gustaría determinar es el rango de fechas entre dos fechas arbitrarias donde a) no hubo evento yb) los eventos se superpusieron.

Así que para un rango de fechas de entrada del 01/04/2009 - 30/06/2009 que se puede esperar a tener los siguientes resultados:

 
no event: 01/04/2009 - 01/05/2009 
overlap : 08/05/2009 - 10/05/2009 
overlap : 10/05/2009 - 12/05/2009 
no event: 13/05/2009 - 20/05/2009 
no event: 22/05/2009 - 24/05/2009 
overlap : 01/06/2009 - 03/06/2009 

Tenga en cuenta que los dos intervalos se superponen adyacentes serían aceptables como uno resultado.

¿Alguien puede ayudarme con un algoritmo de SQL para generar este conjunto de resultados?

EDITAR: La base de datos de la plataforma de destino es SQL Server 2005. Las fechas se registran como 10/05/2009 00:00:00, lo que significa que el evento terminó en algún momento entre el 10/5/2009 00:00:00 y 10/5/2009 23:59:59. Lo mismo es cierto para las fechas de inicio. El intervalo de fechas de entrada también se puede leer como 01/04/2009 00:00:00 - 30/06/2009 23:59:59.

+1

En qué plataforma (s) base de datos va a ser la ejecución de esta consulta? –

Respuesta

4

Es una pequeña variación de la función para aplanar lapsos que se cruzan en SQL Server:

Es uno de los raros casos basados ​​en el cursor enfoque en SQL Server es más rápida es la de una uno basado en conjunto:


CREATE FUNCTION mytable(@p_from DATETIME, @p_till DATETIME) 
RETURNS @t TABLE 
     (
     q_type VARCHAR(20) NOT NULL, 
     q_start DATETIME NOT NULL, 
     q_end DATETIME NOT NULL 
     ) 
AS 
BEGIN 
     DECLARE @qs DATETIME 
     DECLARE @qe DATETIME 
     DECLARE @ms DATETIME 
     DECLARE @me DATETIME 
     DECLARE cr_span CURSOR FAST_FORWARD 
     FOR 
     SELECT startDate, endDate 
     FROM mytable 
     WHERE startDate BETWEEN @p_from AND @p_till 
     ORDER BY 
       startDate 
     OPEN cr_span 
     FETCH NEXT 
     FROM cr_span 
     INTO @qs, @qe 
     SET @ms = @qs 
     SET @me = @qe 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
       FETCH NEXT 
       FROM cr_span 
       INTO @qs, @qe 
       IF @qs > @me 
       BEGIN 
         INSERT 
         INTO @t 
         VALUES ('overlap', @ms, @me) 
         INSERT 
         INTO @t 
         VALUES ('gap', @me, @qs) 
         SET @ms = @qs 
       END 
       SET @me = CASE WHEN @qe > @me THEN @qe ELSE @me END 
     END 
     IF @ms IS NOT NULL 
     BEGIN 
       INSERT 
       INTO @t 
       VALUES (@ms, @me) 
     END 
     CLOSE cr_span 
     RETURN 
END 
GO 

Esta función comprime cada conjunto contiguo de intervalos de intersección en un rango, y devuelve tanto el rango como el siguiente espacio.

+0

¿La respuesta de Quassnoi es una solución al problema? si es así, ¿cuál es el nombre de la tabla de datos en la función? –

+0

+1 Gracias ....... –

1

sin comprender realmente el problema que estamos tratando de resolver, aquí está mi solución a algunos problema de la parte superior de mi cabeza:

  1. Crear función de tabla (UDF) "all-fechas" que haría devolver todas las fechas en un año.
  2. Convierta sus eventos en fechas separadas (una fila de evento se convertiría en tantas filas como días haya) mediante eventos de unión interna a todas las fechas where the date is between event's start and end dates ... Conserve el original eventId.
  3. Realice una combinación externa de las fechas del evento con todas las fechas (una vez más) para encontrar las lagunas o errores.
  4. Únase a las fechas del evento consigo mismo en where dates are same but eventId is not para encontrar superposiciones.
0

mis pobres, con PostgreSQL, que podría hacer que simplemente:

(start1, END1) se solapa (start2, end2) (start1, length1) se solapa (start2, Longitud2)

rendimientos Esta expresión verdadero cuando dos períodos de tiempo (definidos por sus puntos finales) se superponen, falso cuando no se superponen. Los puntos finales se pueden especificar como pares de fechas, horas o marcas de tiempo; o como una fecha, hora o sello de tiempo seguido de un intervalo.

SELECCIONAR (FECHA '2001-02-16', FECHA '2001-12-21') OVERLAPS (FECHA '2001-10-30', FECHA '2002-10-30'); Resultado: true SELECCIONAR (FECHA '2001-02-16', INTERVALO '100 días') OVERLAPS (FECHA '2001-10-30', FECHA '2002-10-30'); Resultado: falsa

pero bajo SQL Server, no sé ... lo siento

Cuestiones relacionadas