日期之间每个月的SELECT行

时间:2016-07-15 12:40:22

标签: sql sql-server tsql

我试图找出如何在一个时期之间为每个月选择一行。该期间将具有表中最早月份的开始日期。因此在下面的示例中,开始时段将是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

基本上我需要复制该行,直到找到另一行或满足句点结束日期,如果找到另一行,则复制该行直到满足结束时段,同时增加为每一行。希望这是有道理的。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

你真的需要Numbers表来解决这类问题。我将在这里使用表变量来模拟它,但是如果在数据库中创建一个合适的变量,请参阅。

以下是解决方案:

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]

答案 1 :(得分: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 rowID=@Current
    select @end=Month from #temp where rowID=@Current+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)<=@end
       )
       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 @Current=@Current+1
end

select * from select * from #MissingData