いくつかの場所で簡略化できます( acct_id
を想定) およびparent_id
NOT NULL
です ):
WITH RECURSIVE search_graph AS (
SELECT parent_id, ARRAY[acct_id] AS path
FROM account
UNION ALL
SELECT g.parent_id, sg.path || g.acct_id
FROM search_graph sg
JOIN account g ON g.acct_id = sg.parent_id
WHERE g.acct_id <> ALL(sg.path)
)
SELECT path[1] AS child
, path[array_upper(path,1)] AS parent
, path
FROM search_graph
ORDER BY path;
- 列
acct_id
、深さコード> 、
cycle
クエリの単なるノイズです。 -
WHERE
条件は、1ステップ前、前に再帰を終了する必要があります 最上位ノードからの重複エントリが結果に含まれます。それはあなたのオリジナルでは「1つずつ」でした。
残りはフォーマットです。
知っている グラフで可能な唯一の円は自己参照です。これを安くすることができます:
WITH RECURSIVE search_graph AS (
SELECT parent_id, ARRAY[acct_id] AS path, acct_id <> parent_id AS keep_going
FROM account
UNION ALL
SELECT g.parent_id, sg.path || g.acct_id, g.acct_id <> g.parent_id
FROM search_graph sg
JOIN account g ON g.acct_id = sg.parent_id
WHERE sg.keep_going
)
SELECT path[1] AS child
, path[array_upper(path,1)] AS parent
, path
FROM search_graph
ORDER BY path;
SQLフィドル。
修飾子( varchar(5)
など)を使用したデータ型には問題(少なくともpg v9.4まで)があることに注意してください。 )配列の連結は修飾子を失いますが、rCTEは正確に一致する型を要求するため:
- 型修飾子を使用したデータ型の驚くべき結果