如果我的 CTE 的递归部分没有联接,每次递归只能得到一行,这是为什么?
在 SQL Server 2016 和 Azure SQL 数据库上测试的代码:
DECLARE @Number TABLE (Number INT);
INSERT INTO @Number (Number)
VALUES (1), (2);
;WITH _cte AS
(
SELECT Number
FROM @Number
UNION ALL
SELECT _cte.Number
FROM _cte
)
SELECT *
FROM _cte
OPTION (MAXRECURSION 2); -- just call recursive part twice to see the issue
在结果中,我在每个递归/深度中得到数字2
。
我希望当前行在每次递归中重复,因此行数呈指数增长
预期输出
Number
--------------------
1 -- from anchor
2
1 -- first recursion
2
1 -- second recursion
2
1
2
实际输出:
Number
--------------------
1 -- from anchor
2
2 -- first recursion
2 -- second recursion
最佳答案
从一些测试来看,SQL 递归似乎是从初始查询返回的最后一行开始深度优先发生的。一旦达到 MAXRECURSION ,查询就会因错误而终止(例如,语句终止。在语句完成之前最大递归 2 已用尽。
)并返回任何结果它在错误发生之前到达。您可以通过在插入语句中插入 2,1 而不是 1,2 或通过在 @Number
表中插入 1,2,3 来验证这一点。如果将 1,2,3 插入到 @Number
中,返回的结果将为
1 -- From anchor
2 -- From anchor
3 -- From anchor
3 -- 1st recursion from last row of anchor query
3 -- Recursion from the row from the line above this (2nd recursion)
-- Query terminates after MAXRECURSION reached on an item and does not attempt recursion on 1 or 2
通常,在使用递归时,您可以使用 where 语句中的某些条件或连接中的 on 条件将 CTE 与其本身或其他表连接起来,这些条件将根据可用数据限制递归(而不仅仅是通过相同的元素)。例如(使用与您的问题相同的 @Number
表):
DECLARE @Number TABLE (Number INT);
INSERT @Number
(
Number
)
VALUES (1),
(2);
WITH _cte2
AS
(SELECT
Number
,0 as 'RecursionCount'
FROM
@Number
UNION ALL
SELECT
Number
,RecursionCount + 1
FROM
_cte2
WHERE
RecursionCount <= 1
)
SELECT * FROM _cte2 OPTION (MAXRECURSION 2);
在上面的示例中,查询将在 where 语句中限制其自身的递归,并且永远不会达到 MAXRECURSION,因此查询将能够完成。您还会注意到,返回结果的顺序证实了我的怀疑,即递归是从最后一项开始的深度优先:
Number RecursionCount
1 0
2 0
2 1
2 2
1 1
1 2
关于sql-server - cte递归部分仅返回一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53228439/