2017-08-24 101 views
1

我有一个日期表这样一个使用CTE:如何在多个记录

Exit_Date  Date_ID 
2017-05-31  1 
2017-04-26  2 
2017-01-02  3 
2016-12-24  4 
2016-11-27  5 

我使用一个循环插入每个这些日期的成CTE来产生近15年来这些日期等这样的:

declare @DI int = 1 
declare @d date 
while @DI <=5 
begin 
select @d = Exit_Date from Date_Table where Date_ID = @DI 
declare @EDTable table (Exit_Date Date); 
with 
    a as(
    select dateadd(yy,-1,@d) d,0 i 
     union all 
    select dateadd(yy,-1,d),i+1 from a where i<14 
), 
    b as(select d,datediff(dd,0,d)%7 dd from a) 
insert into @EDTable select d from b; 
    set @DI = @DI + 1 
end 

的结果是正确的,我得到75行与我的日期。我想知道是否有办法通过从Date_Table中的每个日期记录替换变量@d来摆脱WHILE循环?

+3

如果您的工作代码已经产生了您想要的结果,但正在寻求改进,这可能更适合于Code Review而不是Stack Overflow。 –

+0

@Damien_The_Unbeliever谢谢我不知道代码审查的存在 – JulGreen

+0

看看CROSS APPLY消除循环 –

回答

0

您可以用数字替换表中的循环,或即兴数字表所示:

;with numbers as (
    select top (15) 
    i = row_number() over (order by (select 1)) 
    from [master]..spt_values 
) 
select Exit_Date = dateadd(year,-1*i,d.Exit_Date) 
from Date_Table d 
    cross join numbers n 
where d.Date_id >= 1 
    and d.Date_id <= 5 

rextester演示:http://rextester.com/AQEZ43941


这种方法优于递归的解决方案,尤其是作为行增加数。

参考:

+0

非常感谢你 – JulGreen

+0

@JulGreen乐于帮忙! – SqlZim

0

只需使用表中的递归CTE:

create table #DateTable (
    Date_ID int primary key not null, 
    Exit_Date date not null 
); 

insert into #DateTable (Exit_Date, Date_ID) values 
('2017-05-31',1), 
('2017-04-26',2), 
('2017-01-02',3), 
('2016-12-24',4), 
('2016-11-27',5); 

declare @EDTable table (Exit_Date Date); 

;with a as (
    select dateadd(yy,-1,Exit_Date) d,0 i from #DateTable where Date_ID between 1 and 5 
    union all 
    select dateadd(yy,-1,d),i+1 from a where i<14 
) 
,b as (
    select d,datediff(dd,0,d)%7 dd from a 
) 
insert into @EDTable 
select d from b;