2016-07-15 69 views
0

我正在尝试着解决如何在一个期间之间为每个月选择一行。该期间将具有表格中最早月份的开始日期。因此在下面的示例中,开始时间段将为2016-01-01,但结束时间段将由用户定义,比如说2017-02-01。我的表:在日期之间每个月选择一行

rowID | Month  | someDate | SomeOtherDate | Number 
1  | 2016-01-01 | 2018-01-01 | 2018-01-01 | 0 
2  | 2016-07-01 | 2019-03-01 | 2019-02-01 | 1 

我要找的结果是这样的:

Month  | someDate | SomeOtherDate | Number 
2016-01-01 | 2018-01-01 | 2018-01-01 | 0 
2016-02-01 | 2018-01-01 | 2018-01-01 | 0 
2016-03-01 | 2018-01-01 | 2018-01-01 | 0 
2016-04-01 | 2018-01-01 | 2018-01-01 | 0 
2016-05-01 | 2018-01-01 | 2018-01-01 | 0 
2016-05-01 | 2018-01-01 | 2018-01-01 | 0 
2016-07-01 | 2019-03-01 | 2019-02-01 | 1 
2016-08-01 | 2019-03-01 | 2019-02-01 | 1 
2016-09-01 | 2019-03-01 | 2019-02-01 | 1 
2016-10-01 | 2019-03-01 | 2019-02-01 | 1 
2016-11-01 | 2019-03-01 | 2019-02-01 | 1 
2016-12-01 | 2019-03-01 | 2019-02-01 | 1 
2017-01-01 | 2019-03-01 | 2019-02-01 | 1 
2017-02-01 | 2019-03-01 | 2019-02-01 | 1 

基本上我需要复制的行,直到它找到另一行或满足结束日期,如果其他行发现然后复制该行直到达到结束期限,同时为每行增加。希望这是有道理的。

任何帮助将不胜感激。

+1

你需要再历表,由所有日期填写。你可以在你的查询之前填写它,或者与一些CTE一起“随时”填写。例如http://stackoverflow.com/questions/5635594/how-to-create-a-calender-table-for-100-years-in-sql – xdd

回答

1

对于这类问题,您确实需要Numbers表。我将在这里用table变量来模拟它,但是请大家围绕如何在数据库中创建一个适当的表达式。

这里的解决方案:

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

declare @t table (rowID int, Month date, someDate date, SomeOtherDate date, Number int) 
insert @t values 
(1  , '2016-01-01' , '2018-01-01' , '2018-01-01' , 0), 
(2  , '2016-07-01' , '2019-03-01' , '2019-02-01' , 1) 

declare @end_date date = '20170201' 
set @end_date = dateadd(month, 1, @end_date); 

;with x as (
select *, datediff(month, [month], isnull(lead([month]) over(order by rowid), @end_date)) dd 
from @t 
) 
select dateadd(month, n, [month]) Month, someDate, SomeOtherDate, Number 
from x 
join @num on dd > n 
order by [month] 
+0

谢谢@dean,建议创建一个数字表,并调整稍微查询以包括开始日期,这很好。再次感谢你的帮助。 – DanF

0

试试这个,它会给你丢失的数据,然后尝试惰性您的表

create table #temp(rowID int,Month datetime,someDate datetime,SomeOtherDate datetime,Number int) 

insert into #temp values(1,'2016-01-01','2018-01-01','2018-01-01',0) 
insert into #temp values(2,'2016-07-01','2018-03-01','2019-02-01',1) 
insert into #temp values(3,'2016-09-01','2018-03-01','2019-02-01',1) 

declare @counter int,@Current int 
select @counter=count(1) from #temp 
set @Current=1 

create table #MissingData(rowID int,Month datetime) 

while(@counter>@Current) 
begin 
    DECLARE @start datetime, 
    @end datetime 
    select @start=Month from #temp where [email protected] 
    select @end=Month from #temp where [email protected]+1 
    if(@end is not null) 
    begin 
     ;WITH IntervalDates (datetime) 
     AS 
     (
      SELECT @start 
      UNION ALL 
      SELECT DATEADD(MONTH, 1, datetime) 
      FROM IntervalDates 
      WHERE DATEADD(MONTH, 1, datetime)<[email protected] 
     ) 
     insert into #MissingData 
     SELECT @Current,convert(datetime,Convert(varchar,YEAR(datetime))+'-'+Convert(varchar,MONTH(datetime))+'-01') 
     FROM IntervalDates 
     where convert(datetime,Convert(varchar,YEAR(datetime))+'-'+Convert(varchar,MONTH(datetime))+'-01') not in (@start,@end) 
     order by YEAR(datetime),MONTH(datetime) 
    end 
    select @[email protected]+1 
end 

select * from select * from #MissingData 
相关问题