これらは私の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);
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
私はこの結果を得ています:
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
および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
2番目のcte(rt1
)の最初のSELECT
([root])はこれを返します:
id hid parent_hid hierarchy
11 2 1 2
これは確かにparent_hid = 1
を持つ唯一の行です。再帰的CTEは、この単一の値から始まり、一致するものがなくなるまで階層を下っていきます。
これから、2番目の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
parent_hid = 13
(hid = 13
の行)のid = 190
に一致するものがないため、190で壊れます。
ルートが1で始まる階層のみを探しているため、壊れます。
期待される出力がどうなるかはわかりませんが、親のない階層(つまり、hid
[ルート]にないparent_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
そして、出力は次のようになります。
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
階層を構築するために必要なのは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;
id_hierarchy
のid
は、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
この変更されたクエリで
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
left join id_hierarchy u on (u.hierarchy=h.hid)
)
select id, hid, str as hierarchy
from rt1 where id is not null
order by 1
必要な結果が得られました、
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