2014-06-18 25 views
1

假設我有一個數據集:SQL - 如何根據現有數據集中的日期範圍爲每個月生成行?

rowID | dateStart | dateEnd | Year | Month 
121 | 2013-10-03 | 2013-12-03 | NULL | NULL 
143 | 2013-12-11 | 2014-03-11 | NULL | NULL 
322 | 2014-01-02 | 2014-02-11 | NULL | NULL 

而且我想SQL生成基於該dateStart和dateEnd以下數據源。請注意年份和月份分組。

rowID | dateStart | dateEnd | Year | Month 
121 | 2013-10-03 | 2013-12-03 | 2013 | 10 
121 | 2013-10-03 | 2013-12-03 | 2013 | 11 
121 | 2013-10-03 | 2013-12-03 | 2013 | 12 
143 | 2013-12-11 | 2014-03-11 | 2013 | 12 
143 | 2013-12-11 | 2014-03-11 | 2014 | 1 
143 | 2013-12-11 | 2014-03-11 | 2014 | 2 
143 | 2013-12-11 | 2014-03-11 | 2014 | 3 
322 | 2014-01-02 | 2014-02-11 | 2014 | 1 
322 | 2014-01-02 | 2014-02-11 | 2014 | 2 

我很難把這一個包裹起來。有任何想法嗎?

+0

全部3條回覆!我選擇了Gordon's,因爲它允許我做一個外連接,並忽略具有額外過濾參數的行(我沒有要求這個,但我後來可以實現)。 JBrooks解決方案非常棒,因爲它的佔用空間更小,並且允許我利用函數,而shree的解決方案對於我的大型項目來說有點過於冗長,但仍然完全符合我的需求。謝謝你們! – rodmunera

回答

7

我覺得通過創建一個整數列表然後用它來增加日期來解決這些問題是最容易的。這裏有一個例子:

with nums as (
     select 0 as n 
     union all 
     select n + 1 as n 
     from nums 
     where n < 11 
    ) 
select rowid, datestart, dateend, 
     year(dateadd(month, n.n, datestart)) as yr, 
     month(dateadd(month, n.n, datestart)) as mon 
from table t join 
    nums n 
    on dateadd(month, n.n - 1, datestart) <= dateend; 
+0

以數字11取代11,否則它會在12個月的範圍內跳過一個月。還替換了更改: rodmunera

1

首先,創建一個提交值的函數,它的兩個日期,並返回的年份和月份爲表:

create function dbo.YearMonths(@StartDate DateTime, @EndDate DateTime) 
returns @YearMonths table 
([Year] int, 
[Month] int) 
as 
begin 

    set @EndDate = DATEADD(month, 1, @EndDate) 
    while (@StartDate < @EndDate) 
    begin 

    insert into @YearMonths 
    select YEAR(@StartDate), MONTH(@StartDate) 

    set @StartDate = DATEADD(month, 1, @StartDate) 

    end 

return 
end 

如下面的例子:

select * 
from dbo.YearMonths('1/1/2014', '5/1/2014') 

回報:

enter image description here

然後,你會加入到像這樣得到你想要的東西:

select m.*, ym.Year, ym.Month 
from myTable m 
cross apply dbo.YearMonths(dateStart, dateEnd) ym 
0

試試這個:

declare @months table(mth int) 
insert into @months values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12) 

declare @calendar table(yr int,mth int) 
insert into @calendar 
select distinct year(datestart),mth 
from tbl cross join @months 
union 
select distinct year(dateend),mth 
from tbl cross join @months 

select t.rowID, t.datestart, t.dateend, y.yr [Year], y.mth [Month] 
from 
yourtable t 
inner join @calendar y on year(datestart) = yr or year(dateend) = yr 
where 
(mth >= month(datestart) and mth <= month(dateend) and year(datestart) = year(dateend)) 
or 
(year(datestart) < year(dateend)) 
and 
(year(datestart) = yr and mth >= month(datestart) --All months of start year 
or 
(year(dateend) = yr and mth <= month(dateend))) -- All months of end year 
order by t.rowID, [Year],[Month] 

我們創建了一個「萬年曆錶」,其中列出當前的所有月份和年份組合在源表中。然後,我們根據年份將源表加入日曆表中,並根據需要進行過濾。