Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要了解SQL查询的帮助吗_Sql_Sql Server_Common Table Expression - Fatal编程技术网

需要了解SQL查询的帮助吗

需要了解SQL查询的帮助吗,sql,sql-server,common-table-expression,Sql,Sql Server,Common Table Expression,我有下面的代码,它使用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 nu

我有下面的代码,它使用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);
这是可行的,但我不明白它是如何工作的

尤其是这一部分

numbers AS 
(
    SELECT 1 num

    UNION ALL

    SELECT n.num + 1 num 
    FROM numbers n, totalMonths c
    WHERE n.num <= c.totalM
)
提前谢谢,对不起我的英语

SELECT 1 num
是递归CTE的起点,即第一次迭代中的数字n。在第二次迭代中,第一次迭代的输出

SELECT n.num+1 num FROM numbers n, totalMonths c
WHERE n.num <= c.totalM
变成数字n等等

是递归CTE的起点,即第一次迭代中的数字n。在第二次迭代中,第一次迭代的输出

SELECT n.num+1 num FROM numbers n, totalMonths c
WHERE n.num <= c.totalM

变成数字n等等。

此查询使用两个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的数字。第一个选择指定第一个值1,然后一个指定下一个值,该值比上一个值大int。对递归CTE进行评估是一个很好的方法,因此阅读它们是一个好主意。最后,WHERE指定了停止条件,这样递归就不会永远继续下去

所有这些所做的就是生成一个等价于物理数字表的表,该表只有一列从1开始的数字

最后的SELECT使用数字CTE的结果生成一组日期


请注意,末尾的选项MAXRECURSION 0也与递归CTE相关。这将禁用服务器范围内的递归深度限制,以便在范围很长或烦人的DBA设置了很低的默认限制时,生成查询的数字不会短时间停止。

此查询使用两个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的数字。第一个选择指定第一个值1,然后一个指定下一个值,该值比上一个值大int。对递归CTE进行评估是一个很好的方法,因此阅读它们是一个好主意。最后,WHERE指定了停止条件,这样递归就不会永远继续下去

所有这些所做的就是生成一个等价于物理数字表的表,该表只有一列从1开始的数字

最后的SELECT使用数字CTE的结果生成一组日期

请注意,末尾的选项MAXRECURSION 0也与递归CTE相关。这将禁用服务器范围的递归深度限制,以便在范围很长时,生成数字的查询不会短时间停止,或者麻烦的DBA设置了很低的默认限制。

totalMonths查询将计算为一个标量结果单个值,指示需要生成的月数。这可能更有意义,只是内联执行,而不是使用命名的CTE

numbers生成一系列行,其中一个名为num的列从1开始,到totalM+1结束,这是在上一步中计算的。它可以通过交叉连接引用此值。因为只有一行,所以它基本上只是水平地将这一列附加到表中。查询是递归的,因此每次传递都会向结果中添加一个新行,方法是将1添加到最后添加的行(实际上只是一列),直到先前添加的行的值超过totalM。联合的前半部分是起始值;后半部分通过数字引用自身,并以某种循环的方式递增地构建结果

输出来自输入的数字。从每个num中减去一个,给出从0到totalM的范围,该值被视为添加到开始日期的月数。日期值被转换为长度为6的varchar,这意味着包含日期的最后两个字符被截断

假设@date_开始日期为2016年1月31日,@date_结束日期为2016年3月1日。没有任何实际日期值的比较,因此3月31日在序列中生成并不重要,但也比传递的@date\u end值晚。可以选择相应开始月份和结束月份中的任何日期来生成相同的序列。

totalMonths查询将计算为一个标量结果单个值,指示需要生成的月份数。这可能更有意义,只是内联执行,而不是使用命名的CTE

num bers生成一系列行,其中一列名为num,从1开始,到totalM+1结束,这是在上一步中计算的。它可以通过交叉连接引用此值。因为只有一行,所以它基本上只是水平地将这一列附加到表中。查询是递归的,因此每次传递都会向结果中添加一个新行,方法是将1添加到最后添加的行(实际上只是一列),直到先前添加的行的值超过totalM。联合的前半部分是起始值;后半部分通过数字引用自身,并以某种循环的方式递增地构建结果

输出来自输入的数字。从每个num中减去一个,给出从0到totalM的范围,该值被视为添加到开始日期的月数。日期值被转换为长度为6的varchar,这意味着包含日期的最后两个字符被截断


假设@date_开始日期为2016年1月31日,@date_结束日期为2016年3月1日。没有任何实际日期值的比较,因此3月31日在序列中生成并不重要,但也比传递的@date\u end值晚。可以选择各个开始月份和结束月份中的任何日期来生成相同的序列。

查找递归公共表表达式。。。这里可能有一个重复的帖子:我不会使用递归CTE来。。。获得两个日期范围之间的月份:大量过度杀戮。改为使用数字/计数表…查找递归公共表表达式。。。这里可能有一个重复的帖子:我不会使用递归CTE来。。。获得两个日期范围之间的月份:大量过度杀戮。使用数字/理货表代替。。。