2010-08-13 48 views
11

Ho una tabella T1, contiene un valore NAME (non univoco) e un intervallo di date (D1 e D2 che sono date) Quando NAME è uguale, facciamo un unione della data intervalli (ad esempio B).ORACLE SQL Intersezioni di intervalli di date

Ma come risultato (X), abbiamo bisogno di fare intersezione di tutte le informazioni spazia

Edit: Tabella T1

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

Risultato:

X | 20100313 | 20100415 
X | 20100510 | 20100610 

Visivamente, questo darà il seguente:

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

Risultato:

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

Qualsiasi idea di come ottenere che l'uso di SQL/PL SQL?

+1

Si può provare sovrapposizioni - tuttavia è caratteristica non documentata, http://oraclesponge.wordpress.com/2008/06/12/the-overlaps- predicato/e controlla solo che l'intervallo di dati si sia sovrapposto al periodo –

+0

Puoi mostrare un esempio di colonna/riga effettivo dei valori di colonna della tabella e i valori di dati che desideri vengano restituiti da questa query SQL –

+0

Le intersezioni di data nel risultato sono per quale due nomi? A e C sono nomi diversi e i due intervalli per B non sembrano avere l'intervallo di date in questione. –

risposta

8

qui è una soluzione rapida (non può essere la più efficiente):

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 

costruisco tutti i possibili intervalli di date successive e aderire a questo "calendario" con i dati di esempio. Questo elencherà tutti gli intervalli che hanno 3 valori. Potrebbe essere necessario unire il risultato se si aggiungono righe:

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

Esattamente quello che mi serviva! Merci encore Vincent;) suppongo che potrei sostituire "3" con (selezionare conteggio (distinto NOME) da myData)? – guigui42

+0

ho appena visto il tuo EDIT e non capisco cosa intendi con "se aggiungo una riga". Nella mia tabella di dati, potrei avere nomi illimitati (ad es. ABCDEFG ...) ognuno di essi potrebbe avere righe duplicate (1, 2 o più righe con lo stesso nome) con intervalli di date consecutivi (nessuna sovrapposizione, ma potrebbe avere degli intervalli intermedi, come in il mio esempio B). Quindi, il tuo secondo snippet di codice funzionerà per tutti questi casi? Sto ancora cercando di capire come funzionano i tuoi analisti nella tua query. Grazie ancora ! – guigui42

+0

@ guigui42: la prima query sarà corretta, ma il risultato potrebbe contenere intervalli consecutivi (ad esempio in questo caso '2010-03-13 2010-04-15' e' 2010-04-15 2010-04-16') . La seconda query unirà questi intervalli. –