1

私はPostgreSQLを使用しており、タイプが。のパス列を持つテーブルがありますltree

私が解決しようとしている問題は、ツリー構造全体を考えると、ルートを除いてどの親が最も多くの子を持っているかということです。

サンプルデータは次のようになります。

path column = ; has a depth of 0 and has 11 children its id is 1824 # dont want this one because its the root
path column = ; has a depth of 0 and has 1 children its id is 1823
path column = 1823; has a depth of 1 and has 1 children its id is 1825
path column = 1823.1825; has a depth of 2 and has 1 children its id is 1826
path column = 1823.1825.1826; has a depth of 3 and has 1 children its id is 1827
path column = 1823.1825.1826.1827; has a depth of 4 and has 1 children its id is 1828
path column = 1824.1925.1955.1959.1972.1991; has a depth of 6 and has 5 children its id is 2001
path column = 1824.1925.1955.1959.1972.1991.2001; has a depth of 7 and has 1 children its id is 2141
path column = 1824.1925.1955.1959.1972.1991.2001; has a depth of 7 and has 0 children its id is 2040
path column = 1824.1925.1955.1959.1972.1991.2001; has a depth of 7 and has 1 children its id is 2054
path column = 1824.1925.1955.1959.1972.1991.2001; has a depth of 7 and has 0 children its id is 2253
path column = 1824.1925.1955.1959.1972.1991.2001; has a depth of 7 and has 1 children its id is 2166
path column = 1824.1925.1955.1959.1972.1991.2001.2054; has a depth of 8 and has 0 children its id is 2205
path column = 1824.1925.1955.1959.1972.1991.2001.2141; has a depth of 8 and has 0 children its id is 2161
path column = 1824.1925.1955.1959.1972.1991.2001.2166; has a depth of 8 and has 1 children its id is 2389
path column = 1824.1925.1955.1959.1972.1991.2001.2166.2389; has a depth of 9 and has 0 children its id is 2402
path column = 1824.1925.1983; has a depth of 3 and has 1 children its id is 2135
path column = 1824.1925.1983.2135; has a depth of 4 and has 0 children its id is 2239
path column = 1824.1926; has a depth of 2 and has 5 children its id is 1942
path column = 1824.1926; has a depth of 2 and has 11 children its id is 1928 # this is the row I am after
path column = 1824.1926; has a depth of 2 and has 2 children its id is 1933
path column = 1824.1926; has a depth of 2 and has 2 children its id is 1989
path column = 1824.1926.1928; has a depth of 3 and has 3 children its id is 2051
path column = 1824.1926.1928; has a depth of 3 and has 0 children its id is 2024
path column = 1824.1926.1928; has a depth of 3 and has 2 children its id is 1988

したがって、この例では、ID 1824(ルート)の行には11個の子があり、ID1928の行に深さ2の11個の子があります。これは私が求めている行です。

私はそのことに関してltreeとsqlに不慣れです。

(これは、Ltreeがほとんどの子を持つ親を見つけた後のサンプルデータが追加された改訂された質問ですpostgresqlが閉じられました)。

4

1 に答える 1

6

解決

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

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;

于 2013-03-24T22:26:16.917 に答える