use*_*283 5 sql t-sql sql-server algorithm database-design
我有一张桌子
Users
-------------------------
id | ancestor_id | ....
-------------------------
1 | NULL | ....
2 | 1 | ....
3 | 1 | ....
4 | 3 | ....
5 | 3 | ....
Run Code Online (Sandbox Code Playgroud)
这将代表一棵树
level 1 1
/ \
level 2 2 3
/ \
level 3 4 5
Run Code Online (Sandbox Code Playgroud)
我想创建一个返回的过程i,通过日j日代给定用户的后裔:
CREATE PROCEDURE DescendantsLevel
@user_id INT,
@i INT,
@j INT
AS
....
Run Code Online (Sandbox Code Playgroud)
但是,如果@j是NULL,则返回从生成开始的所有后代@i.
例子:
EXEC DescendantLevel @user_id=1,@i=2,@j=NULL
Run Code Online (Sandbox Code Playgroud)
会回来的
-------------------------
id | ancestor_id | ....
-------------------------
1 | NULL | ....
2 | 1 | ....
3 | 1 | ....
4 | 3 | ....
5 | 3 | ....
Run Code Online (Sandbox Code Playgroud)
和
EXEC DescendantLevel @user_id=1,@i=1,@j=2
Run Code Online (Sandbox Code Playgroud)
会回来的
Users
-------------------------
id | ancestor_id | ....
-------------------------
1 | NULL | ....
2 | 1 | ....
3 | 1 | ....
Run Code Online (Sandbox Code Playgroud)
我有几个问题:
NULL在SQL中表示"无限"概念更好的价值?使用递归 CTE:
DECLARE @test TABLE (id INT NOT NULL, ancestor_id INT NULL)
DECLARE
@id INT = 1,
@i INT = 1,
@j INT = 2
INSERT INTO @test (id, ancestor_id)
VALUES
(1, NULL),
(2, 1),
(3, 1),
(4, 3),
(5, 3)
;WITH CTE_Tree AS
(
SELECT
id,
ancestor_id,
1 AS lvl,
id AS base
FROM
@test
WHERE
id = @id
UNION ALL
SELECT
C.id,
C.ancestor_id,
P.lvl + 1 AS lvl,
P.base AS base
FROM
CTE_Tree P
INNER JOIN @test C ON C.ancestor_id = P.id
WHERE
lvl <= COALESCE(@j, 9999)
)
SELECT
id,
ancestor_id
FROM
CTE_Tree
WHERE
lvl BETWEEN @i AND COALESCE(@j, 9999)
Run Code Online (Sandbox Code Playgroud)
这依赖于不超过 9999 级的递归(实际上 SQL Server 的默认递归限制是 100,因此超过 100 级就会出现错误)。