是否知道父/子关系的最大深度?
然后你可以像在这个例子中那样:
测试
DB<gt;小提琴
here
测试数据:
CREATE TABLE documentdetails
(
ID INT PRIMARY KEY NOT NULL,
Title VARCHAR(30) NOT NULL,
Parent_ID INT,
FOREIGN KEY (Parent_ID) REFERENCES documentdetails (ID)
);
INSERT INTO documentdetails (ID, Title, Parent_ID) VALUES
(1, 'Root', null), (2, 'Introduction', 1), (3, 'Glossary', 1),
(4, 'Audience', 1), (5, 'A', 2), (6,'B', 2), (7, 'C', 2),
(8, 'Foo', null), (9, 'Bar Intro', 8), (10, 'Glossy stuff', 8), (11, 'What The Fook', 8),
(12, 'Yo', 9), (13, 'Ai', 10), (14, 'Potato', 11);
查询:
SELECT
root.ID,
root.Title,
(
SELECT lvl0.ID, lvl0.Title, 0 as Depth,
(
SELECT lvl1.ID, lvl1.Title, 1 as Depth,
(
SELECT lvl2.ID, lvl2.Title, 2 as Depth,
(
SELECT lvl3.ID, lvl3.Title, 3 as Depth
FROM documentdetails lvl3
WHERE lvl3.Parent_ID = lvl2.ID
FOR JSON PATH
) AS Contents
FROM documentdetails lvl2
WHERE lvl2.Parent_ID = lvl1.ID
FOR JSON PATH
) AS Contents
FROM documentdetails lvl1
WHERE lvl1.Parent_ID = lvl0.ID
FOR JSON PATH
) AS Contents
FROM documentdetails lvl0
WHERE lvl0.ID = root.ID
FOR JSON PATH
) AS Contents
FROM documentdetails root
WHERE root.Parent_ID IS NULL;
结果:
ID Title Contents
-- ----- --------
1 Root [{"ID":1,"Title":"Root","Depth":0,"Contents":[{"ID":2,"Title":"Introduction","Depth":1,"Contents":[{"ID":5,"Title":"A","Depth":2},{"ID":6,"Title":"B","Depth":2},{"ID":7,"Title":"C","Depth":2}]},{"ID":3,"Title":"Glossary","Depth":1},{"ID":4,"Title":"Audience","Depth":1}]}]
8 Foo [{"ID":8,"Title":"Foo","Depth":0,"Contents":[{"ID":9,"Title":"Bar Intro","Depth":1,"Contents":[{"ID":12,"Title":"Yo","Depth":2}]},{"ID":10,"Title":"Glossy stuff","Depth":1,"Contents":[{"ID":13,"Title":"Ai","Depth":2}]},{"ID":11,"Title":"What The Fook","Depth":1,"Contents":[{"ID":14,"Title":"Potato","Depth":2}]}]}]
如果你不知道桌子的最大深度?
这里的sql使用递归cte来了解这一点。
WITH RCTE AS
(
SELECT ID as rootID, 0 as lvl, ID, Parent_ID
FROM documentdetails
WHERE Parent_ID IS NULL
UNION ALL
SELECT r.rootID, lvl + 1, t.ID, t.Parent_ID
FROM RCTE r
JOIN documentdetails t ON t.Parent_ID = r.ID
)
SELECT rootID, MAX(lvl) as Depth, COUNT(*) as Nodes
FROM RCTE
GROUP BY rootID
ORDER BY MAX(lvl) DESC, COUNT(*) DESC;
或者相反,从孩子身上播种。
(如果id是主键,那么这可能会更快,因为id上有join)
WITH RCTE AS
(
SELECT ID as baseID, 0 as lvl, ID, Parent_ID
FROM documentdetails
WHERE Parent_ID IS NOT NULL
UNION ALL
SELECT r.baseID, lvl + 1, t.ID, t.Parent_ID
FROM RCTE r
JOIN documentdetails t ON t.ID = r.Parent_ID
)
SELECT ID as rootID, MAX(lvl) as Depth
FROM RCTE
WHERE Parent_ID IS NULL
GROUP BY ID
ORDER BY MAX(lvl) DESC, COUNT(*) DESC;