同じサブツリーの複数の子孫ノードを (潜在的に) 返すクエリからサブツリー (PostgreSQL ltree) のルート ノードを選択する簡単な方法はありますか? このタスクを達成するためにかなり冗長なアルゴリズムを実装しました (インデントおよびフォーマットされた最大 40 行) が、ltree データが実際にはツリーであり、簡単にアクセスできるルート ノードがあるという事実を活用できれば素晴らしいことです。単一のクエリから複数の別個のサブツリー ルートが返される可能性があることに注意することが重要です。そのため、単純にデータを並べ替えて上位の結果を取得することはできません。
2012 年 6 月 7 日: クエリを最新バージョンに更新しました。これにより、時間の複雑さが半分になりました。サブツリーに先祖を持つすべてのノードをサブツリーから削除するために、(必要に応じて)自己アンチ結合を使用します。
基本的に、私のアルゴリズムは次のように機能します。
WITH roots AS
(
/* Place any query here, which returns a field "ancestry" of type ltree */
)
SELECT roots.*
FROM roots
WHERE NOT EXISTS
(
SELECT 1
FROM roots AS ancestors
WHERE ancestors.ancestry @> roots.ancestry
AND ancestors.id <> roots.id
);
(詳細については、私の要旨を参照してください: https://gist.github.com/1507368 )