在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 JOIN
到N
,你会将行数增加10倍。
以上是关于在CTE中使用最大递归来生成CTE,而不是仅在最终的SELECT语句中生成CTE的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server中公用表表达式(CTE)递归的生成帮助数据