6

したがって、隣接リスト内の特定のノードのすべての子を取得する SQL クエリがあります。

WITH    RECURSIVE
        q AS
        (
        SELECT  id, name
        FROM    categories h
        WHERE   id = 11846801
        UNION ALL
        SELECT  hc.id, hc.name
        FROM    q
        JOIN    categories hc
        ON      hc.parent = q.id
        )
SELECT  name
FROM    q

このクエリを変更して、最下位レベルのノードだけを返す方法はありますか? 各パスの深さが異なる可能性があるため、特定のレベルを指定することはできません。

4

3 に答える 3

3

解釈 1

「最初からパスが最も長いノードをすべて残します。」

1 つの方法は、下に向かってレベルをカウントし、一番下のメンバーのみを返すことです。

WITH RECURSIVE q AS (
   SELECT  id, name, 0 AS lvl
   FROM    categories
   WHERE   id = 11846801

   UNION ALL
   SELECT  c.id, c.name, q.lvl + 1
   FROM    q
   JOIN    categories c ON c.parent = q.id
   )
SELECT  id, name
FROM    q
WHERE   lvl = (SELECT max(lvl) FROM q);

解釈 2

「すべてのノードを離れます。」

WITH RECURSIVE q AS (
   SELECT  id, name, parent
   FROM    categories
   WHERE   id = 11846801

   UNION ALL
   SELECT  c.id, c.name, c.parent
   FROM    q
   JOIN    categories c ON c.parent = q.id
   )
SELECT  id, name
FROM    q
WHERE   NOT EXISTS (SELECT FROM q q1 WHERE q1.parent = q.id);

qq が非常に大きい場合を除き、ベース テーブルよりもチェックの方が高速です。その場合、メイン テーブルのインデックスの方が高速な場合があります。

于 2013-02-04T22:42:16.797 に答える
2

一番下にあるものは決して親ではありません。したがって、次のwhere句を追加できます。

where id not in (select parent from categories)

実際、Postgres ではnot in、最も効率的な方法ではない可能性があります。したがって、これはより効率的かもしれません:

where not exists (select 1 from categories c where c.parent = q.id)
于 2013-02-04T22:47:41.307 に答える