我怎样才能编写一个程序来获取i到j或像这样的树?

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)

但是,如果@jNULL,则返回从生成开始的所有后代@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中表示"无限"概念更好的价值?
  • 我该如何实施我所描述的程序?
  • 有没有更好的方法来设计数据库以简化程序?

Tom*_*m H 2

使用递归 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 级就会出现错误)。