我需要获取层次结构表的根节点(具有PARENT_ID = NULL):
ID | PARENT_ID
60 NULL
21 60
11 NULL
23 11
24 21
25 23
14 24
13 25
我想要这个结果:
ID | PARENT_ID | ROOT_ID |
-------------------------
1 NULL NULL
2 1 1
3 1 1
4 2 1
5 4 1
6 NULL NULL
7 6 6
8 7 6
CTE是一个好方法吗?如何创建它?
我可以多拥有一个根节点。我必须为每个节点获取根节点。
这就是我所做的:
;WITH RCTE AS
(
SELECT ID, PARENT_ID, ID as ROOT_ID
FROM TABLE r1
WHERE NOT EXISTS (SELECT * FROM TABLE r2 WHERE r2.ID = r1.PARENT_ID)
UNION ALL
SELECT rh.ID, rh.PARENT_ID,
CASE
WHEN rc.ROOT_ID = rh.ID then NULL
ELSE ROOT_ID
END
FROM dbo.TABLE rh
INNER JOIN RCTE rc ON rc.ID = rh.PARENT_ID
)
select distinct ID, PARENT_ID,
CASE WHEN ROOT_ID = ID THEN NULL
else ROOT_ID
end ROOT_ID
from RCTE
但这是结果:
ID | PARENT_ID | ROOT_ID |
-------------------------
11 NULL NULL
60 NULL NULL
13 25 11
23 11 11
25 23 11
13 25 60
14 24 60
21 60 60
23 11 60
24 21 60
25 23 60
但是您可以看到,我有一些重复项:
ID | PARENT_ID | ROOT_ID |
-------------------------
13 25 60
23 11 60
25 23 60
谢谢!
答案 0 :(得分:2)
类似以下内容应该可以满足您的需求。
WITH recCTE AS
(
SELECT ID,
Parent_ID AS original_Parent_ID,
Parent_ID as next_parent_id,
NULL as ROOT_ID,
CASE WHEN Parent_ID IS NULL THEN 1 END AS is_root
FROM yourtable
UNION ALL
SELECT
reccte.id,
reccte.original_Parent_ID,
yourtable.Parent_ID,
CASE WHEN yourtable.Parent_ID IS NULL THEN reccte.next_parent_id ELSE reccte.ROOT_ID END,
NULL
FROM
recCTE
INNER JOIN yourtable ON reccte.next_parent_id = yourtable.ID
)
SELECT ID, Original_Parent_ID as Parent_ID, ROOT_ID
FROM reccte
WHERE ROOT_ID IS NOT NULL OR is_root = 1
ORDER BY ID;
在递归种子(第一个SELECT)中,我们将抓取所有记录并标记已成为根的记录。
然后在递归项(第二个SELECT)中,查找父记录以查找原始记录。如果其父级为NULL,则填充ROOT_ID
列。
最后,我们从递归CTE中选择填充ROOT_ID的记录或已经是根记录的记录。
CREATE TABLE yourtable (ID int, Parent_ID int);
INSERT INTO yourtable VALUES
(1, NULL),
(2, 1),
(3, 1),
(4, 2),
(5, 4),
(6, NULL),
(7, 6);
WITH recCTE AS
(
SELECT ID,
Parent_ID AS original_Parent_ID,
Parent_ID as next_parent_id,
NULL as ROOT_ID,
CASE WHEN Parent_ID IS NULL THEN 1 END AS is_root
FROM yourtable
UNION ALL
SELECT
reccte.id,
reccte.original_Parent_ID,
yourtable.Parent_ID,
CASE WHEN yourtable.Parent_ID IS NULL THEN reccte.next_parent_id ELSE reccte.ROOT_ID END,
NULL
FROM
recCTE
INNER JOIN yourtable ON reccte.next_parent_id = yourtable.ID
)
SELECT ID, Original_Parent_ID as Parent_ID, ROOT_ID
FROM reccte
WHERE ROOT_ID IS NOT NULL OR is_root = 1
ORDER BY ID;
+----+-----------+---------+
| ID | Parent_ID | ROOT_ID |
+----+-----------+---------+
| 1 | NULL | NULL |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 4 | 2 | 1 |
| 5 | 4 | 1 |
| 6 | NULL | NULL |
| 7 | 6 | 6 |
+----+-----------+---------+