这些是我的 2 个表id_hierarchy
和hierarchy_link
:
CREATE TABLE id_hierarchy
(
id integer NOT NULL,
hierarchy integer
);
insert into id_hierarchy values (11,2),(22,3),(44,5),(77,8),(170,11),
(190,13),(240,18),(255,20);
CREATE TABLE hierarchy_link
(
hid integer NOT NULL,
parent_hid integer
);
insert into hierarchy_link values (1,0),(2,1),(3,2),(5,3),(8,5),(11,8),
(13,11),(15,13),(18,15),(20,18);
Run Code Online (Sandbox Code Playgroud)
与id_hierarchy.hierarchy
=hierarchy_link.hid
对于以下 CTE 查询:
with recursive rt1 as(
select id,hid,parent_hid||'->'||hid as str
from rt2
where rt2.parent_hid=1
union
select t.id,t.hid,s.str||'->'||t.hid as str
from rt2 t
inner join rt1 s on (s.hid=t.parent_hid)
),
rt2 as (
select id, hid, parent_hid, hierarchy
from hierarchy_link h
inner join id_hierarchy u on (u.hierarchy=h.hid)
)
select id, hid, str as hierarchy
from rt1
order by 1
Run Code Online (Sandbox Code Playgroud)
我得到这个结果:
id; hid; hierarchy
11; 2; "1->2"
22; 3; "1->2->3"
44; 5; "1->2->3->5"
77; 8; "1->2->3->5->8"
170; 11; "1->2->3->5->8->11"
190; 13; "1->2->3->5->8->11->13"
Run Code Online (Sandbox Code Playgroud)
中缺少行240,18
和。255,20
id_hierarchy
我的错误在哪里?
如果我们对您的查询进行切片,第一个 cte ( rt2
) 将返回:
id hid parent_hid hierarchy
11 2 1 2
22 3 2 3
44 5 3 5
77 8 5 8
170 11 8 11
190 13 11 13
240 18 15 18
255 20 18 20
Run Code Online (Sandbox Code Playgroud)
SELECT
第二个 cte ( rt1
) 中的第一个([root] ) 返回:
id hid parent_hid hierarchy
11 2 1 2
Run Code Online (Sandbox Code Playgroud)
这确实是唯一的一行parent_hid = 1
。递归 CTE 以这个单一值开始,一直沿着层次结构向下,直到不再有匹配项。
由此看来,第二SELECT
递归地加入rt2
与rt1
上rt1.hid = rt2.parent_id
:
id hid parent_hid hierarchy
11 2 1 2 -+ 1->2 => start
22 3 2 3 -+ -+ 1->2->3 => previous + 3
44 5 3 5 -+ -+ 1->2->3->5 => previous + 5
77 8 5 8 -+ -+ 1->2->3->5->8 => previous + 8
170 11 8 11 -+ -+ 1->2->3->5->8->11 => previous + 11
190 13 11 13 -+ 1->2->3->5->8->11->13 => breaks here
240 18 15 18
255 20 18 20
Run Code Online (Sandbox Code Playgroud)
它在 190 处中断,因为parent_hid = 13
where hid = 13
(row for id = 190
)没有匹配项。
它中断了,因为您只是在寻找以 1 为根的层次结构。
我不确定您的预期输出应该是什么,但是如果您正在寻找没有父级(即parent_hid
不在hid
[根] 中)的层次结构,您也会得到层次结构15->18->20
。
替换where rt2.parent_hid=1
为WHERE NOT EXISTS (SELECT 1 FROM rt2 WHERE hid = r.parent_hid)
和起始根将是:
id hid hierarchy
11 2 1->2
240 18 15->18
Run Code Online (Sandbox Code Playgroud)
输出将是:
id hid hierarchy
11 2 1->2
22 3 1->2->3
44 5 1->2->3->5
77 8 1->2->3->5->8
170 11 1->2->3->5->8->11
190 13 1->2->3->5->8->11->13
240 18 15->18
255 20 15->18->20
Run Code Online (Sandbox Code Playgroud)
似乎只hierarchy_link
需要建立层次结构。因此 rt2 应该被删除:
;WITH rt1 AS (
SELECT hid, parent_hid, CAST(parent_hid as varchar(50)) + '->' + CAST(hid as varchar(50)) as [str]
FROM hierarchy_link r
WHERE r.parent_hid = 1
UNION ALL
SELECT l.hid, l.parent_hid, CAST(r.[str] as varchar(50)) + '->' + CAST(l.hid as varchar(50)) as [str]
FROM hierarchy_link l
INNER JOIN rt1 r ON r.hid = l.parent_hid
)
SELECT h.id, r.hid, r.[str] as hierarchy
FROM rt1 r
INNER JOIN id_hierarchy h ON h.hierarchy = r.hid;
Run Code Online (Sandbox Code Playgroud)
一旦层次结构准备好,id
fromid_hierarchy
只会在最后添加rt1
:
id hid hierarchy
11 2 1->2
22 3 1->2->3
44 5 1->2->3->5
77 8 1->2->3->5->8
170 11 1->2->3->5->8->11
190 13 1->2->3->5->8->11->13
240 18 1->2->3->5->8->11->13->15->18
255 20 1->2->3->5->8->11->13->15->18->20
Run Code Online (Sandbox Code Playgroud)