2008-10-08 375 views
7

您可以讓我知道SQL在重疊時分割日期範圍嗎?SQL日期範圍拆分

數據(與日期範圍的樣品的數據和可能的其他列):

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 

輸出:

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

好吧,我沒有完整的答案,但這裏有一些需要考慮的要點。 1.第一個時間塊是從表組中選擇min(FromDate)FromDate`print(「code sample」);`2.然後第一個塊的結束是從表組中選擇min(FromDate)FromDate,FromDate> 「塊的開始」3.根據需要重複。 :) – Craig 2008-10-08 22:23:49

回答

6

這應該可以解決問題(MySQL的方言,但很容易適應)

初始設置

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 

查詢

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` 

結果

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的答案適用於SQL服務器:

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