Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL-如何根据现有数据集中的日期范围为每个月生成行?_Sql Server_Sql Server 2012 - Fatal编程技术网

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]