all union all in common table expression

时间:2012-10-20 09:53:25

标签: sql recursive-query

我正在玩cte打印1到10或打印12个月

create table eventlist 
  (
    id int identity(1,1) not null, 
    edate smalldatetime 
  )
  select * from eventlist

  insert into eventlist select '01/01/2012'




  ;with cte AS
    (
       select edate from eventlist 
       union all 

       select dateadd(M,1,edate) from cte where MONTH(edate)<12


    )

    select MONTH(edate), YEAR (edate) from cte

但突然之间我只是将ct这样的另一个联盟所有分区组合在一起

;with cte AS
    (
       select edate from eventlist 
       union all 

       select dateadd(M,1,edate) from cte where MONTH(edate)<12
       union all 
       select dateadd(Y,1,edate) from cte where YEAR(edate)<2013

    )

    select MONTH(edate), YEAR (edate) from cte

当我刚运行时,我会收到此错误

声明终止。在语句完成之前,最大递归100已用尽。

我理解这个错误是由于recurssion的限制但是 i just want to understand how will this recurssion will work ?

1 个答案:

答案 0 :(得分:1)

Y是DateOfYear的缩写,不是年份的缩写。请尝试yyyyyy,或者更好地year

您得到的错误是因为您超过了recusrion限制。您要求CTE从日期('2012-01-01')开始,在每个(递归)步骤中,生成一个月后的第二天('2012-01-01'第一步)第二天(第一步'2012-01-02')。然后在第二步中,将产生另外4行,对于第1步中产生的每个新行,将产生2行。然后是8,然后是16,等等(条件MONTH(edate)<12只有在第11步产生2 ^ 10个新行后才有效。即使这样,它也只会略微限制在第11步产生的行数。接下来的步骤。如果没有递归限制,原始查询将创建数百万行。

这就是为什么你的CTE不会像你期望的那样返回24行,而是因为双重递归而返回90(即使你将Y更改为Year)。

使用此:

; with cte AS
(
   select edate from eventlist 
   union all 
   select dateadd(Month,1,edate) from cte where MONTH(edate)<12
)

, cte2 AS
(
   select edate from cte 
   union all 
   select dateadd(Year,1,edate) from cte2 where YEAR(edate)<2013
)

select MONTH(edate), YEAR(edate) from cte2 ;

或者我觉得这个更简单:

; with cte AS
(
   select edate from eventlist 
   union all 
   select dateadd(Month,1,edate) from cte where edate < '2013-12-01'
)

select MONTH(edate), YEAR(edate) from cte ;