以下代码将在SQL Server 2008R2上打印当年的所有日期
with x (dy, yr)
as (
select dy, year (dy) yr
from (
select getdate () - datepart (dy, getdate ()) + 1 dy
-- the first date of the current year
) tmp1
union all
select dateadd (dd, 1, dy), yr
from x
where year (dateadd (dd, 1, dy)) = yr
)
select x.dy
from x
option (maxrecursion 400)
但有一点我无法理解
[Err] 42000 - [SQL Server]语句终止。最大值 在语句完成之前,递归363已经用尽。
但处理器如何知道语句何时完成?
答案 0 :(得分:4)
您在这里处理的是递归CTE 。你应该read more关于它是如何工作的。
基本上,
它从锚点(第一个SELECT,UNION ALL的左侧部分)获取第一行集。
该行集在第二个SELECT(UNION ALL的右侧部分)中变为别名x
,称为递归部分。
递归部分基于x
生成另一个行集,在下一次迭代中成为新的x
。也就是说,不初始x
和最后一个结果集的组合行集成为新x
,但仅最后一个结果集
对新的x
再次重复上一步,循环继续,直到其中任何一个为真:
另一次迭代不产生结果集;
达到MAXRECURSION限制。
最终结果集包含从递归CTE的两个部分获得的所有部分结果集。
将以上内容应用于您的特定查询:
第一个SELECT生成一行,其中包含今年的1月1日(日期)的1 st ,这将成为第一个x
表。
对于x
的每一行,第二个SELECT会生成一个包含相应下一个日期的行如果它属于同一年。因此,递归部分的第一次迭代有效地为我们提供了1月份的2 nd 。根据以上描述,结果集变为新的x
。
以下迭代产生1月份的3 rd ,下一次产生4 th ,依此类推。
如果MAXRECURSION选项值已安全地允许我们在x
包含12月的31 st 的时刻到达,则另一次迭代将显示第二天事实属于不同的一年。这将导致产生一个空行集,这反过来将导致终止递归CTE的执行。
答案 1 :(得分:1)
这不是答案,这只是编写sql的另一种方式。 Andriy M给你一个很酷的答案,你应该给他正确的答案。
;with x (dy)
as (
select dateadd(year, datediff(year, 0, getdate()), 0) dy
union all
select dy + 1
from x
where year (dy) = year(dy+1)
)
select x.dy
from x
option (maxrecursion 400)