分层SQL查询:从给定结束节点id的[nodeid,parentid]pairs表中获取树的整个分支的最佳SQL查询
有没有任何方法可以在SQL中发送递归查询 给定结束节点id,我需要按级别排序到根节点(其parentid=NULL)的所有行。例如,如果我有以下情况:分层SQL查询:从给定结束节点id的[nodeid,parentid]pairs表中获取树的整个分支的最佳SQL查询,sql,tree,hierarchical-data,recursive-query,hierarchical-query,Sql,Tree,Hierarchical Data,Recursive Query,Hierarchical Query,有没有任何方法可以在SQL中发送递归查询 给定结束节点id,我需要按级别排序到根节点(其parentid=NULL)的所有行。例如,如果我有以下情况: nodeid | parentid a | NULL b | a c | b nodeid | parentid | depth a | NULL | 0 b | a | 1 c | b | 2 查询完end\u
nodeid | parentid
a | NULL
b | a
c | b
nodeid | parentid | depth
a | NULL | 0
b | a | 1
c | b | 2
查询完end\u node\u id=c
,我会得到如下结果:
nodeid | parentid
a | NULL
b | a
c | b
nodeid | parentid | depth
a | NULL | 0
b | a | 1
c | b | 2
(除了深度,我还可以使用到给定端点节点的距离)
我能想到的唯一(也是显而易见的)方法是每行执行一次查询,直到到达父节点为止
有更有效的方法吗?如果您使用的是mssql 2005+,您可以这样做: 测试数据:
DECLARE @tbl TABLE(nodeId VARCHAR(10),parentid VARCHAR(10))
INSERT INTO @tbl
VALUES ('a',null),('b','a'),('c','b')
查询
;WITH CTE
AS
(
SELECT
tbl.nodeId,
tbl.parentid,
0 AS Depth
FROM
@tbl as tbl
WHERE
tbl.parentid IS NULL
UNION ALL
SELECT
tbl.nodeId,
tbl.parentid,
CTE.Depth+1 AS Depth
FROM
@tbl AS tbl
JOIN CTE
ON tbl.parentid=CTE.nodeId
)
SELECT
*
FROM
CTE
对于Oracle,根据注释中的要求,您可以使用运算符生成层次结构,并使用
level
伪列获取深度:
SELECT nodeid, parentid, LEVEL
FROM t
START WITH parentid IS NULL
CONNECT BY parentid = PRIOR nodeid;
以以下解决方案结束(其中level是到结束节点的距离) Oracle,使用(感谢@Mureinik提供的信息): 示例:使用视图,使其归结为单个标准SQL查询(要求>=10g): Postgres>=8.4,使用查询: 使用视图的示例,可将其归结为单个标准SQL查询:
CREATE OR REPLACE VIEW VNODES AS
WITH RECURSIVE BRANCH(IDBRANCH,IDPARENTCATEGORY,IDCATEGORY,LVL) AS (
SELECT IDCATEGORY AS IDBRANCH, IDPARENTCATEGORY, IDCATEGORY, 1 AS LVL FROM TNODES
UNION ALL
SELECT pr.IDBRANCH, p.IDPARENTCATEGORY, p.IDCATEGORY, LVL+1
FROM BRANCH pr, TNODES p
WHERE p.IDCATEGORY = pr.IDPARENTCATEGORY
)
SELECT IDBRANCH, IDCATEGORY, IDPARENTCATEGORY, LVL
FROM BRANCH;
SELECT * FROM VNODES WHERE IDBRANCH = 122 ORDER BY LVL ASC;
您使用的是什么RDBMS?它必须适用于Oracle和Postgres(尽管通用解决方案是理想的)
和递归的
()似乎适用于Postgres。现在我需要一个Oracle解决方案检查下面我的答案是否有Oracle解决方案我已将其标记为已接受,因为START WITH/CONNECT BY正是Oracle解决方案所需的,尽管实际查询略有不同(end node id是提供的节点id,而不是根节点id)。请查看我的答案以了解实际的解决方案。(很抱歉,我没有接受您的答案,您向我展示了在Oracle中获得所需解决方案所需的全部内容,但我觉得我必须提供更详细的答案,说明如何在Oracle和postgresql中使用视图,将问题简化为一个简单的标准SQL select查询)这与接受的解决方案有相同的问题:我希望提供一个结束节点ID来获得分支而不是根节点ID,但是这样做是一个简单的改变,所以我认为它也是一个有效的答案。
CREATE OR REPLACE VIEW VNODES AS
WITH RECURSIVE BRANCH(IDBRANCH,IDPARENTCATEGORY,IDCATEGORY,LVL) AS (
SELECT IDCATEGORY AS IDBRANCH, IDPARENTCATEGORY, IDCATEGORY, 1 AS LVL FROM TNODES
UNION ALL
SELECT pr.IDBRANCH, p.IDPARENTCATEGORY, p.IDCATEGORY, LVL+1
FROM BRANCH pr, TNODES p
WHERE p.IDCATEGORY = pr.IDPARENTCATEGORY
)
SELECT IDBRANCH, IDCATEGORY, IDPARENTCATEGORY, LVL
FROM BRANCH;
SELECT * FROM VNODES WHERE IDBRANCH = 122 ORDER BY LVL ASC;