SQL - how do I generate rows for each month based on date ranges in existing dataset?

烈酒焚心 提交于 2019-12-03 16:34:51

I find it easiest to approach these problems by creating a list of integers and then using that to increment the dates. Here is an example:

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;

First, create a tabled-valued function that takes the 2 dates and returns the year and month as a table:

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

As an example the following:

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

returns:

Then you would join to it like this to get what you wanted:

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

Try this:

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]

We create a 'Calendar table' which lists all the month and year combinations present in the source table. Then, we join the source table to the calendar table based on the year, and filter as required.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!