在CTE中使用最大递归来生成CTE,而不是仅在最终的SELECT语句中生成CTE

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在CTE中使用最大递归来生成CTE,而不是仅在最终的SELECT语句中生成CTE相关的知识,希望对你有一定的参考价值。

我想在预定的开始和结束日期之间生成一列日期,并将结果存储在CTE中以在我的查询中使用。下面的递归方法确实有效,但在CTE中使用maxrecursion似乎是不可能的。还有另一种方法吗?

(1)这很好:

DECLARE @startnum INT=1
DECLARE @endnum INT=10000
;
WITH gen AS (       
    SELECT @startnum AS num
    UNION ALL
    SELECT num+1 FROM gen WHERE num+1<=@endnum
)

SELECT * FROM gen
option (maxrecursion 10000)

(2)这不起作用:

DECLARE @StartDate DATE; 
DECLARE @EndDate DATE;
SET @StartDate = '20150406'; 
SET @EndDate = '20190406';

DECLARE @startnum INT=1
DECLARE @endnum INT=10000
;
WITH gen AS (       
    SELECT @startnum AS num
    UNION ALL
    SELECT num+1 FROM gen WHERE num+1<=@endnum
)
,

num_list as (
SELECT * FROM gen
option (maxrecursion 10000)
)
,

tab_dates as (
SELECT  DATEADD(DAY, nbr - 1, @StartDate) AS Dates
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.num) AS Nbr
          FROM      num_list c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
)
SELECT * FROM tab_dates
答案

您可以在最终选择的末尾添加maxrecursion选项。该选项适用于所有CTE。

将整个事物视为一个单一的陈述,它就是这样。

我知道这似乎违反直觉。我第一次遇到这个问题时很困惑。

另一答案

而不是使用RBAR rCTE,使用Tally。你也可以用CTE来做这件事。你不会遇到这种最大递归问题,而且速度要快得多:

WITH N AS (
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1 --10
         CROSS JOIN N N2 --100
         CROSS JOIN N N3 --1000
         CROSS JOIN N N4 --10000
    )
SELECT *
FROM Tally;

通过上面的例子,你可以在CTE计数器中继续进行CROSS JOINN,你会将行数增加10倍。

以上是关于在CTE中使用最大递归来生成CTE,而不是仅在最终的SELECT语句中生成CTE的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server中公用表表达式(CTE)递归的生成帮助数据

sql server使用cte递归查询获取树形的父节点/子节点

sql递归cte在视图中不能正常工作

表数据子集上的递归 CTE

递归 CTE 通过多个级别更新父记录

sqlserver实现树形结构递归查询(无限极分类)