うーん、私は以前にこのようなことをしていたと思います。当時、私には階層があり、問題は「ノードXのすべての子と孫を見つける」ことでした。これはリレーショナルデータベースで行うのは簡単ではありません。そのため、ヘルパーテーブルとそれを設定するためのスクリプトを作成しました。私がそれを思い出せるかどうか見てみましょう...注:これは私の記憶の後で自由に行われ、テストされていません。私がそれを正しく理解したことを保証するものではありません。私の問題もあなたの問題とは少し異なっていたので、解決策が当てはまるかどうかはわかりません。
create table chain_helper (
head int,
tail int,
chain_length int
)
create index chain_helper_by_head(head);
create index chain_helper_by_tail(tail);
このテーブルには、ヘッドとテールが外部キーである可能性のあるすべてのリンクが含まれているという考え方です。階層が厳密で、ループ制御が不要なため、私の場合は少し簡単でした。ソーステーブルにはidフィールドとparent_idフィールドがありました。これが私がテーブルに入力した方法です:
単純なリンクを使用してテーブルを初期化します。
insert into chain_helper (head, tail, chain_length)
select id, parent_id, 1 from source_table;
長さ2のすべてのチェーンをテーブルに追加し続けました。
insert into chain_helper (head, tail, chain_length)
select parent.head, child.tail, min(parent.chain_length + 1)
from chain_helper parent
join source_table child on source_table.parent_id=parent.id
where not exists
(select * from chain_helper where head=parent.head and tail=child.tail)
group by parent.head, child.tail;
(私は厳密な階層を持っていたので、集約する必要はありませんでした-私の場合、重複はありません)。
繰り返すと、長さ3などのすべてのチェーンが挿入され、挿入するものがなくなるまで、ステートメントをすべて繰り返すことができます。次に、チェーンの最大長を見つけるのは簡単です。
select max(chain_length) from chain_helper;
このソリューションでは、チェーンを簡単に表示することはできませんが、私の場合はそれは必須ではありませんでした。私は主に、結合でchain_helperを使用して、階層内の特定のノードのすべての子と孫をキャッチできるようにしました。つまり、「このサブツリーの総収益」です。
select sum(source_table.revenue)
from source_table join chain_helper on chain_helper.tail = source_table.id
where chain_helper.head = parent_of_subtree;