需要帮助了解
我一直在使用一个CTE需要帮助了解
declare
@date_start DateTime,
@date_end DateTime
;WITH totalMonths AS
(
SELECT
DATEDIFF(MONTH, @date_start, @date_end) totalM
),
numbers AS
(
SELECT 1 num
UNION ALL
SELECT n.num + 1 num
FROM numbers n, totalMonths c
WHERE n.num <= c.totalM
)
SELECT
CONVERT(varchar(6), DATEADD(MONTH, numbers.num - 1, @date_start), 112)
FROM
numbers
OPTION (MAXRECURSION 0);
这个工程下面的代码,得到两个日期范围之间的几个月SQL查询,但我不明白它是如何工作
特别是这部分
numbers AS
(
SELECT 1 num
UNION ALL
SELECT n.num + 1 num
FROM numbers n, totalMonths c
WHERE n.num <= c.totalM
)
在此先感谢,对不起我的英语
此查询使用两个CTE(一个递归)来从无到有生成一个值列表(SQL并不擅长这样做)。
totalMonths AS (SELECT DATEDIFF(MONTH, @date_start, @date_end) totalM),
这部分,基本上是DATEDIFF
的结果结合到名称totalM
一个令人费解的方式。这可能已经实现只是一个变量,如果你能申报物品:
DECLARE @totalM int = DATEDIFF(MONTH, @date_start, @date_end);
那么你当然会使用@totalM
来引用值。
numbers AS (
SELECT 1 num
UNION ALL
SELECT n.num+1 num FROM numbers n, totalMonths c
WHERE n.num<= c.totalM
)
这部分基本上是使用递归来生成数字1到totalMonths
实现一个简单的循环。第一个SELECT
指定第一个值(1),之后的那个指定下一个值,它的int大于前一个值。评估递归CTE有somewhat special semantics,所以最好阅读它们。最后,WHERE
指定停止条件,以便递归不会永远持续下去。
所有这些都会生成一个等同于物理“数字”的表格,其中只有一列是从1开始的数字。
最后的SELECT
使用numbers
CTE的结果生成一堆日期。请注意0最后也与递归CTE相关。这会禁用服务器范围的递归深度限制,以便在范围非常长的情况下生成查询的数字不会停止,或者令人烦恼的DBA设置非常低的默认限制。
SELECT 1 num
是你的递归CTE的起点,这是(数n)在第一teration.In第二迭代出来把第一
SELECT n.num+1 num FROM numbers n, totalMonths c
WHERE n.num <= c.totalM
变成数(n)和等。
totalMonths
查询的计算结果为标量结果(单值),表示需要生成的月数。使用内联代替使用命名的CTE可能更有意义。
numbers
生成的行的顺序与一个称为num
起始于1
和totalM + 1
其计算在前面步骤结束列。它可以通过交叉连接来引用该值。由于只有一行,它基本上只是将这一列附加到表中。该查询是递归的,因此每次通过将1行添加到最后添加的行(实际上只是一列),直到之前添加的行的值超过totalM
,结果向结果添加新行。 union
的前半部分是起始值;下半部分通过from numbers
参照本身,并逐步建立循环结果。
输出来自numbers
输入。从num
中减去一个,给出从0
到totalM
的范围,并且该值被视为要添加到开始日期的月数。日期值被转换为长度为6的varchar
,这意味着包含该日的最后两个字符被截断。
假设@date_start
是2016年1月31日,而@date_end
是2016年3月1日。实际日期值从来没有任何比较,因此无关紧要的是3月31日在序列中生成,但也落后于通过@date_end
值。可以选择相应开始和结束月份中的任何日期以生成相同的序列。
查找递归公用表表达式...这里可能是一个重复的帖子:http://stackoverflow.com/questions/14274942/sql-server-cte-and-recursion-example – sgeddes
我不会使用递归CTE “...在两个日期范围之间获得月份”:巨大的过度杀伤力。使用数字/计数表代替... –