Sql server SQL-如何根据现有数据集中的日期范围为每个月生成行?
假设我有一个数据集:Sql server SQL-如何根据现有数据集中的日期范围为每个月生成行?,sql-server,sql-server-2012,Sql Server,Sql Server 2012,假设我有一个数据集: 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
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
我很难在这件事上下定决心。有什么想法吗?我发现解决这些问题最简单的方法是创建一个整数列表,然后用它来增加日期。以下是一个例子:
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;
首先,创建一个表值函数,该函数采用两个日期并将年和月作为表返回:
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 m.*, ym.Year, ym.Month
from myTable m
cross apply dbo.YearMonths(dateStart, dateEnd) ym
试试这个:
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]
我们创建了一个“日历表”,其中列出了源表中存在的所有月份和年份组合。然后,我们根据年份将源表加入日历表,并根据需要进行筛选。喜欢所有3个响应!我选择Gordon的,因为它允许我进行外部连接,并忽略具有额外过滤参数的行。我没有要求这样做,但后来我能够实现它。JBrooks解决方案非常棒,因为它占用的空间更小,并且允许我利用函数,而shree的解决方案对于我更大的项目来说有点过于冗长,但仍然完全满足了我的需要。谢谢大家!!在NUM中将10替换为11,否则它将在12个月的范围内跳过一个月。也替换为:<替换为
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]