SQL中的层次搜索

SQL中的层次搜索,sql,sql-server,firebird,recursive-query,Sql,Sql Server,Firebird,Recursive Query,我有下表 ID CATALOGUE SWID PARENTSWID LEVEL 1 1 1 1 0 2 1 2 1 1 3 1 3 1 1 4 1 4 2 2 5 1 5 4 3 6

我有下表

ID   CATALOGUE  SWID   PARENTSWID   LEVEL
1       1         1         1         0
2       1         2         1         1
3       1         3         1         1 
4       1         4         2         2
5       1         5         4         3
6       1         6         5         4
7       2         2         2         0
8       2         3         2         1
所以我想要所有元素
(SWID)
,它们都有
PARENTSWID=“1”

根级别始终为“
0
”,根元素具有相同的
SWID
PARENTSWID

树的深度没有界限。 稍后,我将不得不使用
catalog
属性限制搜索,但现在我需要一个如何设置的想法

那么,有人做过类似的事情吗?:)

问候 塞米尔


尝试此操作时,我得到错误“未知ISC错误336397226”
我查找了这个错误,它意味着:
336397226 dsql\u cte\u cycle cte'@1'具有循环依赖性

我的桌子和这里的桌子有相同的项目


(我已经在IBWSQL上试用了它,并选择了我的DB)

这适用于SQLServer2005+

DECLARE @PARENTSWID int = 1
;WITH cte as
(
SELECT ID, CATALOGUE, SWID, PARENTSWID, LEVEL
FROM table
WHERE PARENTSWID = @PARENTSWID
AND LEVEL = 0
UNION ALL
SELECT t.ID, t.CATALOGUE, t.SWID, t.PARENTSWID, t.LEVEL
FROM table t
JOIN CTE ON cte.ID = t.PARENTSWID
AND t.LEVEL = cte.LEVEL +1
)
SELECT ID, CATALOGUE, SWID, PARENTSWID, LEVEL FROM cte
OPTION (MAXRECURSION 0)

请参阅。

这是我使用公共表表达式为Firebird SQL提供的解决方案

CREATE TABLE STACKOVERFLOW0001 (
    ID          INTEGER,
    CATALOUGE   INTEGER,
    SWID        INTEGER,
    PARENTSWID  INTEGER,
    "LEVEL"     INTEGER
);

INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (1, 1, 1, 1, 0);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (2, 1, 2, 1, 1);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (3, 1, 3, 1, 1);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (4, 1, 4, 2, 2);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (5, 1, 5, 4, 3);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (6, 1, 6, 5, 4);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (7, 2, 2, 2, 0);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (8, 2, 3, 2, 1);

COMMIT WORK;

Query 

WITH RECURSIVE cat (id,catalouge,swid,parentswid,lvl)
as
(
    select id,catalouge,swid,parentswid,"LEVEL" from stackoverflow0001 as r
    where r."LEVEL" = 0 -- Magic Happens here for Filtering, you can specify the Start of the recursive tree walk down from here.


    union all

    select r.id, r.catalouge, r.swid, r.parentswid,r."LEVEL" from stackoverflow0001 as r,cat
    where cat.swid = r.parentswid -- This is what matches up the first query record to the child records
    and r."LEVEL" > 0 -- Just an additional filter check for child records.
)

select * from cat
// You can also stick some where clauses here if you need

Output

ID  CATALOUGE   SWID    PARENTSWID  LVL
1   1   1   1   0
2   1   2   1   1
4   1   4   2   2
5   1   5   4   3
6   1   6   5   4
8   2   3   2   1
3   1   3   1   1
7   2   2   2   0
4   1   4   2   2
5   1   5   4   3
6   1   6   5   4
8   2   3   2   1
8   2   3   2   1

(1,2,3,4,5,6)中的output.SWID是什么?因为它们都是parent=1的后代。如果删除变量并且将语句终止字符(
)移动到它所属的位置,则Firebird也可以使用它。一匹没有名字的马非常感谢你澄清这一点。我只熟悉sqlserver。谢谢@X.L.Ant为您提供了一把小提琴。这把小提琴非常好(在小提琴上)我也会用firebird试试,并给您一个反馈。再次感谢:)将在一个新的答案中发布哇,这似乎有效:))但是有一个问题,如果我在声明中的“Union all”后面加上where子句,就像你在“select*from cat”后面所说的那样(我指的是速度方面的差异),有什么区别吗
CREATE TABLE STACKOVERFLOW0001 (
    ID          INTEGER,
    CATALOUGE   INTEGER,
    SWID        INTEGER,
    PARENTSWID  INTEGER,
    "LEVEL"     INTEGER
);

INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (1, 1, 1, 1, 0);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (2, 1, 2, 1, 1);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (3, 1, 3, 1, 1);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (4, 1, 4, 2, 2);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (5, 1, 5, 4, 3);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (6, 1, 6, 5, 4);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (7, 2, 2, 2, 0);
INSERT INTO STACKOVERFLOW0001 (ID, CATALOUGE, SWID, PARENTSWID, "LEVEL")
                       VALUES (8, 2, 3, 2, 1);

COMMIT WORK;

Query 

WITH RECURSIVE cat (id,catalouge,swid,parentswid,lvl)
as
(
    select id,catalouge,swid,parentswid,"LEVEL" from stackoverflow0001 as r
    where r."LEVEL" = 0 -- Magic Happens here for Filtering, you can specify the Start of the recursive tree walk down from here.


    union all

    select r.id, r.catalouge, r.swid, r.parentswid,r."LEVEL" from stackoverflow0001 as r,cat
    where cat.swid = r.parentswid -- This is what matches up the first query record to the child records
    and r."LEVEL" > 0 -- Just an additional filter check for child records.
)

select * from cat
// You can also stick some where clauses here if you need

Output

ID  CATALOUGE   SWID    PARENTSWID  LVL
1   1   1   1   0
2   1   2   1   1
4   1   4   2   2
5   1   5   4   3
6   1   6   5   4
8   2   3   2   1
3   1   3   1   1
7   2   2   2   0
4   1   4   2   2
5   1   5   4   3
6   1   6   5   4
8   2   3   2   1
8   2   3   2   1