2010-08-13 11 views
11

Mam tabelę T1, zawiera ona wartość NAZWA (nie jest unikatowa) i zakres dat (D1 i D2, które są datami) Gdy NAME są takie same, tworzymy unię daty zakresy (np. B).ORACLE SQL Koniec zakresu dat

Ale w wyniku (X), musimy dokonać przecięcia wszystkich zakresów dat

Edit: Tabela T1

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

Wynik:

X | 20100313 | 20100415 
X | 20100510 | 20100610 

Wizualnie to poda:

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

Wynik:

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

Każdy pomysł jak dostać się, że za pomocą SQL/PL SQL?

+1

Można spróbować pokrywa się - jednak jest to nieudokumentowana funkcja, http://oraclesponge.wordpress.com/2008/06/12/the-overlaps- predykat/i jedyne jego sprawdzenia, że ​​zakres danych ma cały okres –

+0

Czy można wyświetlić rzeczywisty przykład kolumny/wiersza wartości kolumny z tabeli i wartości danych, które mają zostać zwrócone przez to zapytanie SQL –

+0

Przecięcia daty w wyniku są wyświetlane dla których dwie nazwy? A i C są różnymi nazwami, a dwa zakresy dla B nie wydają się mieć danego zakresu dat. –

Odpowiedz

8

o to szybkie rozwiązanie (nie może być najbardziej efektywne):

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 

zbudować wszystkie możliwe zakresy kolejne daty i dołączyć do „Kalendarz” z przykładowymi danymi. Spowoduje to wyświetlenie wszystkich zakresów, które mają 3 wartości. Być może trzeba połączyć wynik jeśli dodać wiersze:

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

Dokładnie to, czego potrzebowałem! Merci encore Vincent;) przypuszczam, że mógłbym zastąpić "3" (wybierz liczbę (różne NAME) z myData)? – guigui42

+0

Właśnie widziałem twoją EDYTĘ, i naprawdę nie rozumiem, co masz na myśli przez "jeśli dodaję wiersz". W mojej tabeli danych mogę mieć nieograniczoną liczbę nazw (np. ABCDEFG ...), każdy może mieć zduplikowane wiersze (1, 2 lub więcej wierszy o tej samej nazwie) z kolejnymi zakresami dat (bez nakładania się, ale może mieć przerwy pomiędzy, np. mój przykład B). Czy Twój drugi fragment kodu będzie działać we wszystkich tych przypadkach? Wciąż próbuję dowiedzieć się, jak twoi analitycy pracują w twoim zapytaniu. Dzięki jeszcze raz ! – guigui42

+0

@ guigui42: pierwsze zapytanie będzie poprawne, ale wynik może zawierać kolejne interwały (na przykład w tym przypadku "2010-03-13 2010-04-15" i "2010-04-15 2010-04-16") . Drugie zapytanie połączy te interwały. –

Powiązane problemy