2015-06-10 89 views
0

我想在數據集中找到給定的日期範圍,並將它們劃分爲範圍內每天的唯一行(下面的示例)。在SQL中做相反的事很簡單,但我努力實現所需的查詢輸出。SQL到行的分支日期範圍

開始數據:

ITEM START_DATE END_DATE 
A  1/1/2015 1/5/2015 
B  2/5/2015 2/7/2015 

所需的查詢輸出:

ITEM DATE_COVERED 
A  1/1/2015 
A  1/2/2015 
A  1/3/2015 
A  1/4/2015 
A  1/5/2015 
B  2/5/2015 
B  2/6/2015 
B  2/7/2015 
+1

看起來像一個有趣的問題。你有什麼疑問試過自己? –

+0

可能重複的[SQL如何將日期範圍的行轉換爲許多行與每個日期](http://stackoverflow.com/questions/16358959/sql-how-to-convert-row-with-date-range-to -many-rows-with-each-date) –

回答

2

最快的方式將一些符合表:

DECLARE @t TABLE 
    (
     ITEM CHAR(1) , 
     START_DATE DATE , 
     END_DATE DATE 
    ) 
INSERT INTO @t 
VALUES ('A', '1/1/2015', '1/5/2015'), 
     ('B', '2/5/2015', '2/7/2015') 



;WITH cte AS(SELECT -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) d FROM 
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t1(n) CROSS JOIN 
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t2(n) CROSS JOIN 
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t3(n) CROSS JOIN 
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t4(n)) 

SELECT t.ITEM, ca.DATE_COVERED FROM @t t 
CROSS APPLY(SELECT DATEADD(dd, d, t.START_DATE) AS DATE_COVERED 
      FROM cte 
      WHERE DATEADD(dd, d, t.START_DATE) BETWEEN t.START_DATE AND t.END_DATE) ca 
ORDER BY t.ITEM, ca.DATE_COVERED 
+0

如何預測交叉連接添加與CTE,當日期差異非常long.like('A','1/1/1965','1/5/2015 ') –

+1

@VinitPatel,只需添加更多的交叉連接以確保覆蓋所有範圍,但是我懷疑他需要多於5個交叉連接,因爲5個連接將覆蓋275年。 6年加入2732年。 –

1

查詢:

SQLFiddleExample

SELECT t.ITEM, 
     DATEADD(day,n.number, t.START_DATE) AS DATE_COVERED 
FROM Table1 t, 
(SELECT number 
FROM master..spt_values 
WHERE [type] = 'P') n 
WHERE START_DATE <= DATEADD(day,n.number, t.START_DATE) 
AND END_DATE >= DATEADD(day,n.number, t.START_DATE) 

結果:

| ITEM | DATE_COVERED | 
|------|--------------| 
| A | 2015-01-01 | 
| A | 2015-01-02 | 
| A | 2015-01-03 | 
| A | 2015-01-04 | 
| A | 2015-01-05 | 
| B | 2015-02-05 | 
| B | 2015-02-06 | 
| B | 2015-02-07 | 
1

注意:如果您的開始日期和結束日期之間的差異是最大的2047天內僅適用(master..spt_values只允許0..2047範圍值)

select item, dateadd(d,v.number,d.start_date) adate 
from begindata d 
join master..spt_values v on v.type='P' 
      and v.number between 0 and datediff(d, start_date, end_date) 
order by adate; 

我想說我這樣做是自己,但我從this

得到的代碼

這裏是你的預期result

+0

在你的代碼有限制,recoreds高達2048沒有更多recoreds那裏.... –

+0

我剛剛檢查了我的小提琴,並得到了2053的結果,之後,我做了4096個結果通過改變兩個開始日期到一年2000所以我不知道你的意思@VinitPatel –

+0

ITEM START_DATE END_DATE A 1/1/1985 1/5/2015試試這個,告訴我@Jeremy C. –

0

試試這個小提琴...

CREATE TABLE Table1 
    ([ITEM] varchar(1), [START_DATE] date, [END_DATE] date) 
; 

INSERT INTO Table1 
    ([ITEM], [START_DATE], [END_DATE]) 
VALUES ('A', '2015-01-01', '2015-01-05'), ('B', '2015-02-05', 2015-02-07'); 

WITH Days 
      AS (SELECT ITEM, START_DATE AS [Date], 1 AS [level] from Table1 
       UNION ALL 
       SELECT TABLE1.ITEM, DATEADD(DAY, 1, [Date]), [level] + 1 
       FROM  Days,Table1 
       WHERE DAYS.ITEM=TABLE1.ITEM AND [Date] < END_DATE) 
    SELECT distinct [Date] 
    FROM Days 

DEMO