2010-08-13 124 views
11

Tengo una tabla T1, contiene un valor NAME (no exclusivo) y un rango de fechas (D1 y D2 que son fechas) Cuando NAME es el mismo, hacemos una unión de la fecha rangos (por ejemplo, B).ORACLE SQL Intervalos de intervalo de fechas

Pero como resultado (X), tenemos que hacer intersección de todos los periodos de tiempo

Editar: Tabla T1

NAME | D1  | D2 
A | 20100101 | 20101211 
B | 20100120 | 20100415 
B | 20100510 | 201
C | 20100313 | 20100610 

Resultado:

X | 20100313 | 20100415 
X | 20100510 | 20100610 

Visualmente, este dará lo siguiente:

NAME  : date range 
A   : [-----------------------]----- 
B   : --[----]---------------------- 
B   : ----------[---------------]--- 
C   : -----[--------]--------------- 

Resultado:

X   : -----[-]---------------------- 
X   : ----------[---]--------------- 

alguna idea de cómo conseguir que el uso de SQL/PL SQL?

+1

Puede intentar superposiciones - sin embargo, es característica no documentada, http://oraclesponge.wordpress.com/2008/06/12/the-overlaps- predicado/y solo comprueba que el rango de datos se superpuso período –

+0

Puede mostrar un ejemplo de columna/fila real de los valores de columna de su tabla y los valores de datos que desea que devuelva esta consulta SQL –

+0

Las intersecciones de fecha en el resultado son para que dos nombres? A y C son nombres diferentes y los dos rangos para B no parecen tener el rango de fechas en cuestión. –

Respuesta

8

aquí es una solución rápida (puede no ser la más eficiente):

SQL> CREATE TABLE myData AS 
    2 SELECT 'A' name, date'2010-01-01' d1, date'2010-12-11' d2 FROM DUAL 
    3 UNION ALL SELECT 'B', date'2010-01-20', date'2010-04-15' FROM DUAL 
    4 UNION ALL SELECT 'B', date'2010-05-10', date'2010-12-30' FROM DUAL 
    5 UNION ALL SELECT 'C', date'2010-03-13', date'2010-06-10' FROM DUAL; 

Table created 

SQL> WITH segments AS (
    2 SELECT dat seg_low, lead(dat) over(ORDER BY dat) seg_high 
    3 FROM (SELECT d1 dat FROM myData 
    4   UNION 
    5   SELECT d2 dat FROM myData) 
    6 ) 
    7 SELECT s.seg_low, s.seg_high 
    8 FROM segments s 
    9 JOIN myData m ON s.seg_high > m.d1 
10     AND s.seg_low < m.d2 
11 GROUP BY s.seg_low, s.seg_high 
12 HAVING COUNT(DISTINCT NAME) = 3; 

SEG_LOW  SEG_HIGH 
----------- ----------- 
13/03/2010 15/04/2010 
10/05/2010 10/06/2010 

construyo todos los posibles rangos de fechas sucesivas y me uno a este "calendario" con los datos de la muestra. Esto mostrará una lista de todos los rangos que tienen 3 valores. Puede que tenga que combinar el resultado si se agrega filas:

SQL> insert into mydata values ('B',date'2010-04-15',date'2010-04-16'); 

1 row inserted 

SQL> WITH segments AS (
    2 SELECT dat seg_low, lead(dat) over(ORDER BY dat) seg_high 
    3 FROM (SELECT d1 dat FROM myData 
    4   UNION 
    5   SELECT d2 dat FROM myData) 
    6 ) 
    7 SELECT MIN(seg_low), MAX(seg_high) 
    8 FROM (SELECT seg_low, seg_high, SUM(gap) over(ORDER BY seg_low) grp 
    9    FROM (SELECT s.seg_low, s.seg_high, 
10       CASE 
11        WHEN s.seg_low 
12         = lag(s.seg_high) over(ORDER BY s.seg_low) 
13        THEN 0 
14        ELSE 1 
15       END gap 
16      FROM segments s 
17      JOIN myData m ON s.seg_high > m.d1 
18         AND s.seg_low < m.d2 
19      GROUP BY s.seg_low, s.seg_high 
20     HAVING COUNT(DISTINCT NAME) = 3)) 
21 GROUP BY grp; 

MIN(SEG_LOW) MAX(SEG_HIGH) 
------------ ------------- 
13/03/2010 16/04/2010 
10/05/2010 10/06/2010 
+0

¡Exactamente lo que necesitaba! Merci encore Vincent;) supongo que podría reemplazar "3" con (seleccionar count (distinct NAME) from myData)? – guigui42

+0

acabo de ver tu EDIT, y realmente no entiendo lo que quieres decir con "si agrego una fila". En mi tabla de datos, podría tener nombres ilimitados (por ejemplo, ABCDEFG ...) cada uno podría tener filas duplicadas (1, 2 o más líneas con el mismo nombre) con intervalos de fechas consecutivos (sin superposición, pero podría tener espacios intermedios, como en mi ejemplo B). Entonces, ¿funcionará su segundo fragmento de código para todos estos casos? Todavía estoy tratando de descubrir cómo funcionan tus análisis en tu consulta. Gracias de nuevo ! – guigui42

+0

@ guigui42: la primera consulta será correcta, pero el resultado puede contener intervalos consecutivos (por ejemplo, en este caso '2010-03-13 2010-04-15' y' 2010-04-15 2010-04-16') . La segunda consulta fusionará estos intervalos. –

Cuestiones relacionadas