2

私は非常に多くのReddit /スラッシュドットのように、フォーラムを構築しています、すなわちのPostgres:ツリー構造を保持したまま並べ替え/人気子供を注文する(常に子供上記両親)

  • 無制限の返信ネスト
  • (好き/投票順)人気のコメントは(自分の営巣/深さレベルの範囲内)のトップに上昇しますが、ツリー構造を保持する必要があります(親が常に直接子どもたちの上に示されている)

ここですサンプルテーブル& da TA:

DROP TABLE IF EXISTS "comments"; 
CREATE TABLE comments (
    id BIGINT PRIMARY KEY, 
    parent_id BIGINT, 
    body TEXT NOT NULL, 
    like_score BIGINT, 
    depth BIGINT 
); 

INSERT INTO comments VALUES ( 0, NULL, 'Main top of thread post', 5 , 0); 

INSERT INTO comments VALUES ( 1, 0, 'comment A', 5 , 1); 
INSERT INTO comments VALUES ( 2, 1, 'comment A.A', 3, 2); 
INSERT INTO comments VALUES ( 3, 1, 'comment A.B', 1, 2); 
INSERT INTO comments VALUES ( 9, 3, 'comment A.B.A', 10, 3); 
INSERT INTO comments VALUES (10, 3, 'comment A.B.B', 5, 3); 
INSERT INTO comments VALUES (11, 3, 'comment A.B.C', 8, 3); 
INSERT INTO comments VALUES ( 4, 1, 'comment A.C', 5, 2); 

INSERT INTO comments VALUES (5, 0, 'comment B', 10, 1); 
INSERT INTO comments VALUES (6, 5, 'comment B.A', 7, 2); 
INSERT INTO comments VALUES (7, 5, 'comment B.B', 5, 2); 
INSERT INTO comments VALUES (8, 5, 'comment B.C', 2, 2); 

ここで私は、これまでに作ってみた再帰クエリのですが、私は子供を注文する方法を見つけ出すが、(親は常に子供を超えるべきである)ツリー構造を保持することはできません...

WITH RECURSIVE tree AS (
    SELECT 
    ARRAY[]::BIGINT[] AS sortable, 
    id, 
    body, 
    like_score, 
    depth 
    FROM "comments" 
    WHERE parent_id IS NULL 

    UNION ALL 

    SELECT 
    tree.sortable || "comments".like_score || "comments".id, 
    "comments".id, 
    "comments".body, 
    "comments".like_score, 
    "comments".depth 
    FROM "comments", tree 
    WHERE "comments".parent_id = tree.id 
) 
SELECT * FROM tree 
ORDER BY sortable DESC 

これは出力...

+----------------------------------------------------------+ 
|sortable  |id|body     |like_score|depth| 
+----------------------------------------------------------+ 
|{10,5,7,6} |6 |comment B.A   |7   |2 | 
|{10,5,5,7} |7 |comment B.B   |5   |2 | 
|{10,5,2,8} |8 |comment B.C   |2   |2 | 
|{10,5}  |5 |comment B    |10  |1 | 
|{5,1,5,4}  |4 |comment A.C   |5   |2 | 
|{5,1,3,2}  |2 |comment A.A   |3   |2 | 
|{5,1,1,3,10,9}|9 |comment A.B.A   |10  |3 | 
|{5,1,1,3,8,11}|11|comment A.B.C   |8   |3 | 
|{5,1,1,3,5,10}|10|comment A.B.B   |5   |3 | 
|{5,1,1,3}  |3 |comment A.B   |1   |2 | 
|{5,1}   |1 |comment A    |5   |1 | 
|    |0 |Main top of thread post|5   |0 | 
+----------------------------------------------------------+ 

...しかし "コメントB"、 "コメントA" と "スレッドポストのメイントップ" 子供たちを下回っていることがわかり?文脈の秩序を維持するにはどうしたらいいですか?つまり、私が欲しいの出力は次のようになります。

+----------------------------------------------------------+ 
|sortable  |id|body     |like_score|depth| 
+----------------------------------------------------------+ 
|    |0 |Main top of thread post|5   |0 | 
|{10,5}  |5 |comment B    |10  |1 | 
|{10,5,7,6} |6 |comment B.A   |7   |2 | 
|{10,5,5,7} |7 |comment B.B   |5   |2 | 
|{10,5,2,8} |8 |comment B.C   |2   |2 | 
|{5,1}   |1 |comment A    |5   |1 | 
|{5,1,5,4}  |4 |comment A.C   |5   |2 | 
|{5,1,3,2}  |2 |comment A.A   |3   |2 | 
|{5,1,1,3}  |3 |comment A.B   |1   |2 | 
|{5,1,1,3,10,9}|9 |comment A.B.A   |10  |3 | 
|{5,1,1,3,8,11}|11|comment A.B.C   |8   |3 | 
|{5,1,1,3,5,10}|10|comment A.B.B   |5   |3 | 
+----------------------------------------------------------+ 

私は実際にユーザーが、多数の方法でソートできるようにしたい:

  • 一番人気のある最初の
  • 少なくとも第一
  • 人気順新しい順
  • 最古の最初の最初の
  • など

...いずれの場合も、両親は子供の上に表示する必要があります。しかし、ここでは例として「like_score」を使用しています。そこから残りの部分を把握できるはずです。

ウェブを調査して自分自身で試していて、近くにいるように感じるが、この最後の部分を理解することはできない。

答えて

1
tree.sortable || -"comments".like_score || "comments".id 
       ^
       /|\ 
        | 
        | 

ORDER BY sortable 

WITH RECURSIVE tree AS (
    SELECT 
    ARRAY[]::BIGINT[] AS sortable, 
    id, 
    body, 
    like_score, 
    depth 
    FROM "comments" 
    WHERE parent_id IS NULL 

    UNION ALL 

    SELECT 
    tree.sortable || -"comments".like_score || "comments".id, 
    "comments".id, 
    "comments".body, 
    "comments".like_score, 
    "comments".depth 
    FROM "comments", tree 
    WHERE "comments".parent_id = tree.id 
) 
SELECT * FROM tree 
ORDER BY sortable 

+-------------------+----+-------------------------+------------+-------+ 
| sortable   | id | body     | like_score | depth | 
+-------------------+----+-------------------------+------------+-------+ 
| (null)   | 0 | Main top of thread post | 5   | 0  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-10,5}   | 5 | comment B    | 10   | 1  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-10,5,-7,6}  | 6 | comment B.A    | 7   | 2  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-10,5,-5,7}  | 7 | comment B.B    | 5   | 2  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-10,5,-2,8}  | 8 | comment B.C    | 2   | 2  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1}   | 1 | comment A    | 5   | 1  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1,-5,4}  | 4 | comment A.C    | 5   | 2  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1,-3,2}  | 2 | comment A.A    | 3   | 2  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1,-1,3}  | 3 | comment A.B    | 1   | 2  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1,-1,3,-10,9} | 9 | comment A.B.A   | 10   | 3  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1,-1,3,-8,11} | 11 | comment A.B.C   | 8   | 3  | 
+-------------------+----+-------------------------+------------+-------+ 
| {-5,1,-1,3,-5,10} | 10 | comment A.B.B   | 5   | 3  | 
+-------------------+----+-------------------------+------------+-------+ 
+0

恐ろしく、ありがとうございます!私はいくつかの「0フィールド」のものを早く試しましたが、間違ったASC/DESCの順序で間違った場所にいきました。だから私は '|| "コメント" .id'は現在冗長で、削除することはできますか?違いの非常に明確な説明とサンプル出力を含めてくれてありがとう、非常に理解しやすいです。 – YeB

+1

あなたは大歓迎です:-)同じレベルの「like_score」と等しい場合にはタイドブレーカーであるため、私は「id」を削除しません –

+0

ああ、あなたは正しいのですか?もうそれは必要ありません。また、どのようにしてASCII出力テーブルを生成しましたか?それを生成するSQL GUIを使用していますか? – YeB

0

これを確認します。

WITH RECURSIVE tree AS (
    SELECT 
    ARRAY[]::BIGINT[] AS sortable, 
    id, 
    body, 
    like_score, 
    depth, 
    lpad(id::text, 2, '0') as path 
    FROM "comments" 
    WHERE parent_id IS NULL 

    UNION ALL 

    SELECT 
    tree.sortable || "comments".like_score || "comments".id, 
    "comments".id, 
    "comments".body, 
    "comments".like_score, 
    "comments".depth, 
    tree.path || '/' || lpad("comments".id::text, 2, '0') as path 
    FROM "comments", tree 
    WHERE "comments".parent_id = tree.id 
) 
SELECT * FROM tree 
ORDER BY path 

あなたが欲しい桁のどんな数でlpadにパラメータ2を置き換えることができますので、予めご了承ください。

+0

要求された結果に対する結果を確認してください –

+0

@DuduMarkovitzあなたは正しいです。あなたの答えは正しいです。 – wind39

関連する問題