0

私は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

しかし、突然、このようにcteのすべてのセクションで別のユニオンを組み合わせるだけです

;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 を使い果たしました。

再帰の制限によるこのエラーは理解していますが、 i just want to understand how will this recurssion will work ?

4

1 に答える 1

1

Y is the abbreviation for DateOfYear, not for year. Try yy or yyyy or even better the year.

The error you get is because you exceed the recusrion limit. You are asking the CTE to start from a date ('2012-01-01') and in every (recursion) step, produce the day after a month ('2012-01-01' for the first step) and the next day ('2012-01-02' for the first step). Then in the second step, 4 more rows will have to be produced, 2 for each new row produced in the 1st step. Then 8, then 16, etc. (The condition MONTH(edate)<12 will be effective only after you have produced 2^10 new rows in the 11th step. Even then, it will only slightly limit the number of the rows produced in the next steps. Your original query if there was no recursion limit would create millions of rows).

That's why your CTE will return not 24 rows as you expect, but 90 instead (even when you change Y to Year), because of the double recursion.

Use this:

; 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 ;

or this one which is I think simpler:

; 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 ;
于 2012-10-20T10:17:12.380 に答える