2008-10-08 9 views
7

Czy możesz podać mi kod SQL, aby podzielić zakresy dat, gdy się pokrywają?Zakres dat SQL Split

danych (przykładowe dane z zakresu dat i ewentualnie innych kolumnach):

Col1 FromDate ToDate 
1. 1 1/1/2008 31/12/2010 
2. 1 1/1/2009 31/12/2012 
3. 1 1/1/2009 31/12/2014 

wyjściowa:

Col1 From Date ToDate 
1. 1  1/1/2008 31/12/2008 (from row 1 above) 
2. 1  1/1/2009 31/12/2010 (from rows 1,2 and 3 above) 
3. 1  1/1/2011 31/12/2012 (from rows 2 and 3 above) 
4. 1  1/1/2013 31/12/2014 (from row 3 above) 
+0

Ok, nie mam pełną odpowiedź, ale oto kilka punktów do rozważenia. 1. Pierwszym blokiem czasu jest min (FromDate) z grupy tabel przez FromDate'print ("próbka kodu"); '2. Następnie koniec pierwszego bloku jest wybierany min (FromDate) z grupy tabel przez FromDate, gdzie FromDate> "początek bloku" 3. Powtórzyć w razie potrzeby. :) – Craig

Odpowiedz

6

To powinno załatwić sprawę (MySQL dialektem, ale łatwo dostosować)

Początkowa konfiguracja

SQL query: SELECT * FROM `test` LIMIT 0, 30 ; 
Rows: 3 
start  end 
2008-01-01 2010-12-31 
2009-01-01 2012-12-31 
2009-01-01 2014-12-31 

Zapytanie

SELECT 
    `start` , min(`end`) 
FROM (
    SELECT t1.start, t2.end 
    FROM test t1, test t2 
    WHERE t1.start < t2.end 
    UNION 
    SELECT t1.end + INTERVAL 1 DAY , t2.end 
    FROM test t1, test t2 
    WHERE t1.end + INTERVAL 1 DAY < t2.end 
    UNION 
    SELECT t1.start, t2.start - INTERVAL 1 DAY 
    FROM test t1, test t2 
    WHERE t1.start < t2.start - INTERVAL 1 DAY 
) allRanges 
GROUP BY `start` 

Wynik

start  min(`end`) 
2008-01-01 2008-12-31 
2009-01-01 2010-12-31 
2011-01-01 2012-12-31 
2013-01-01 2014-12-31 
2

Skliwz za odpowiedź przystosowany dla SQL Server:

DECLARE @DateTest TABLE 
(
    FromDate datetime, 
    ToDate datetime 
) 

insert into @DateTest (FromDate, ToDate) 
(
select cast('1/1/2008' as datetime), cast('12/31/2010' as datetime) 
union 
select cast('1/1/2009' as datetime), cast('12/31/2012' as datetime) 
union 
select cast('1/1/2009' as datetime), cast('12/31/2014' as datetime) 
) 

SELECT 
    FromDate , min(ToDate) 
FROM (
    SELECT t1.FromDate, t2.ToDate 
    FROM 
    @DateTest t1, 
    @DateTest t2 
    WHERE t1.FromDate < t2.ToDate 

    UNION 

    SELECT dateadd(DAY, 1, t1.ToDate), t2.ToDate 
    FROM 
    @DateTest t1, 
    @DateTest t2 
    WHERE dateadd(DAY, 1, t1.ToDate) < t2.ToDate 
) allRanges 
group by FromDate