sql >> データベース >  >> RDS >> PostgreSQL

ほとんどの子を持つ親を見つけるためのPostgresqlltreeクエリ。ルートを除く

    解決策

    子が最も多いノードを見つけるには:

    SELECT subpath(path, -1, 1), count(*) AS children
    FROM   tbl
    WHERE  path <> ''
    GROUP  BY 1
    ORDER  BY 2 DESC
    LIMIT  1;
    

    ...そしてルートノードを除外します:

    SELECT *
    FROM  (
       SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
       FROM   tbl
       WHERE  path <> ''
       GROUP  BY 1
       ) ct
    LEFT   JOIN (
       SELECT tbl_id
       FROM   tbl
       WHERE  path = ''
       ) x USING  (tbl_id)
    WHERE  x.tbl_id IS NULL
    ORDER  BY children DESC
    LIMIT  1
    

    ルートノードに空のltreeがあると仮定します ('' )パスとして。 NULLの可能性があります 。次に、path IS NULLを使用します ...

    あなたの例の勝者は実際には2001です 、5人の子供がいます。

    -> SQLfiddle

    どのように?

    • 関数 subpath(...) 追加モジュールltreeによって提供されます

    • 最後のノードを取得します 負のオフセットのパス内 、要素の直接の親です。

    • その親が表示される頻度をカウントし、ルートノードを除外して、カウントが最も高い残りのノードを取得します。

    • ltree2text()を使用します ltreeから値を抽出します 。

    • 複数のノードに同じように最も多くの子がある場合、例では任意のノードが選択されます。

    テストケース

    これは、(ノイズをトリミングした後)有用なテストケースに到達するために私がしなければならなかった作業です:

    SQLfiddle を参照してください。 。

    言い換えれば、次回は有用なテストケースを提供することを忘れないでください。

    追加の列

    コメントへの回答。
    まず、テストケースを展開します:

    ALTER TABLE tbl ADD COLUMN postal_code text
                  , ADD COLUMN whatever serial;
    UPDATE tbl SET postal_code = (1230 + whatever)::text;
    

    ご覧ください:

    SELECT * FROM tbl;
    

    単にJOIN ベーステーブルの親への結果:

    SELECT ct.*, t.postal_code
    FROM  (
       SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
       FROM   tbl
       WHERE  path <> ''
       GROUP  BY 1
       ) ct
    LEFT   JOIN (
       SELECT tbl_id
       FROM   tbl
       WHERE  path = ''
       ) x USING  (tbl_id)
    JOIN  tbl t USING (tbl_id)
    WHERE  x.tbl_id IS NULL
    ORDER  BY children DESC
    LIMIT  1;



    1. Oracle Bug Databaseはどこにありますか?

    2. Railsの1つのクエリでオブジェクトのオブジェクトを取得する

    3. ユリウス日をPostgreSQLの日付に変換する

    4. SQL、数値の補助テーブル