Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 我怎样才能编写一个程序,从I到j或类似这样的树获取级别?_Sql_Sql Server_Algorithm_Tsql_Database Design - Fatal编程技术网

Sql 我怎样才能编写一个程序,从I到j或类似这样的树获取级别?

Sql 我怎样才能编写一个程序,从I到j或类似这样的树获取级别?,sql,sql-server,algorithm,tsql,database-design,Sql,Sql Server,Algorithm,Tsql,Database Design,我有一张像这样的桌子 Users ------------------------- id | ancestor_id | .... ------------------------- 1 | NULL | .... 2 | 1 | .... 3 | 1 | .... 4 | 3 | .... 5 | 3 | .... 那将代表一棵像树一样的树 level 1

我有一张像这样的桌子

        Users
-------------------------
id | ancestor_id | ....
-------------------------
 1 |    NULL     | ....
 2 |     1       | ....
 3 |     1       | ....
 4 |     3       | ....
 5 |     3       | ....
那将代表一棵像树一样的树

   level 1           1
                   /  \ 
   level 2        2    3 
                      / \
   level 3           4   5
我想创建一个过程,返回给定用户的第I代到第j代后代:

CREATE PROCEDURE DescendantsLevel 
   @user_id INT,
   @i INT,
   @j INT
AS
   ....
但是,如果@j为NULL,它将返回从@i代开始的所有子代

示例:

会回来吗

-------------------------
id | ancestor_id | ....
-------------------------
 1 |    NULL     | ....
 2 |     1       | ....
 3 |     1       | ....
 4 |     3       | ....
 5 |     3       | ....

会回来吗

        Users
-------------------------
id | ancestor_id | ....
-------------------------
 1 |    NULL     | ....
 2 |     1       | ....
 3 |     1       | ....
我有几个问题:

在SQL中,有比NULL更好的值来表示无穷大的概念吗? 我如何实现我描述的过程? 是否有更好的数据库设计方法来简化过程? 使用递归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)

这依赖于不超过9999个递归级别—实际上SQL Server的递归默认限制为100,因此超过100个级别时,您将得到一个错误。

Lookup recursive ctes。如果您使用此设计,这将是解决此问题的最简单方法。您还可以将嵌套集模型视为邻接列表的更好替代方案。如果在第一个示例中@i为2,那么为什么返回id 1?为什么不添加级别列?使查询变得非常简单。添加级别列会将手动计算的列添加到表中-这会增加复杂性,然后可能会失去同步并导致其他问题。
        Users
-------------------------
id | ancestor_id | ....
-------------------------
 1 |    NULL     | ....
 2 |     1       | ....
 3 |     1       | ....
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)