2016-05-11 15 views
1

Ich habe drei Tabellen Beiträge, Kommentare und Benutzer. Posts-Tabelle enthält zwei Arten von Posts, Frage und Antwort. Kommentare werden zu Fragen und Antworten abgegeben. Mein Ziel ist es, eine einzige Frage mit Kommentaren, Antworten darauf und Kommentare zu diesen Antworten zu bekommen. Ich brauche auch den Benutzernamen aus der Tabelle users als Autor für jede Frage, Antwort und Kommentar, den ich hole. Ich verwende Postgres 9.5 und nutze die json_agg() Funktion.Repetitive Einträge in SQL JOIN Abfrage

Während Beispielausgabe, die ich brauche, sollte etwas ähnlich dem ersten folgenden sein, bekomme ich wiederholte Einträge.

Was fehlt mir hier? Korrekte Gruppierung nach Klauseln kann sein. Oder die Unterabfrage, um die Antworten mit ihren Kommentaren zu sammeln, ist nicht der richtige Weg. Wenn ich den linken Join aus den Beiträgen in der Kommentartabelle austiere, bekomme ich die gewünschten Ergebnisse ohne Kommentare zu Fragen. Auch wenn ich den linken Join, der die Unterabfrage enthält, abbringe, erhalte ich nicht-wiederholende Ergebnisse, wie ich es erwarte, und wiederum ist dies nicht der vollständige Datensatz, den ich begehre. Dies sind Dinge, die ich bisher gesammelt habe, um mein Problem zu lösen.

Was ich brauche:

[ 
    { 
    "post_id": "10", 
    "created_at": "2016-05-10T00:16:54.469Z", 
    "post_type": "question", 
    "post_title": "qwerty", 
    "post_text": "asdasd asda sdasd", 
    "post_author_id": 1, 
    "author": "isikfsc", 
    "parent_post_id": null, 
    "is_accepted": null, 
    "acceptor_id": null, 
    "answers": [ 
     { 
     "post_id": 17, 
     "created_at": "2016-05-10T04:58:56.350229", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "222asda dasdad asdada", 
     "post_author_id": 1, 
     "author": "isikfsc", 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 5, 
      "created_at": "2016-05-10T10:56:30.220128", 
      "text": "qweqwe", 
      "author_id": 1, 
      "author": "isikfsc", 
      "parent_post_id": 17 
      }, 
      { 
      "id": 8, 
      "created_at": "2016-05-10T11:00:00.182991", 
      "text": "sasasd", 
      "author_id": 1, 
      "author": "isikfsc", 
      "parent_post_id": 17 
      } 
     ] 
     }, 
     { 
     "post_id": 14, 
     "created_at": "2016-05-10T04:19:19.005556", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "asdasdasdasd", 
     "post_author_id": 1, 
     "author": "isikfsc", 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 2, 
      "created_at": "2016-05-10T05:25:34.671008", 
      "text": "qeqweqwe", 
      "author_id": 1, 
      "author": "isikfsc", 
      "parent_post_id": 14 
      } 
     ] 
     } 
    ], 
    "comments": [ 
     { 
      "id": 1, 
      "created_at": "2016-05-10T10:56:30.220128", 
      "text": "qweqwe", 
      "author_id": 1, 
      "author": "isikfsc", 
      "parent_post_id": 10 
     }, 
     { 
      "id": 4, 
      "created_at": "2016-05-10T11:00:00.182991", 
      "text": "sasasd", 
      "author_id": 1, 
      "author": "isikfsc", 
      "parent_post_id": 10 
     } 
    ] 
    } 
] 

Meine Frage ist:

SELECT 
    q.*, 
    json_agg(ac.*) AS answers, 
    json_agg(c.*) AS comments --comments on posts of post_id questions 
FROM posts q 

LEFT JOIN 
    (
     SELECT 
      a.*, 
      json_agg(c.*) AS comments -- comments on posts of post_id answers 
     FROM posts a 
     LEFT JOIN comments c 
     ON a.post_id = c.parent_post_id 

     GROUP BY a.post_id 
    ) ac 
ON q.post_id = ac.parent_post_id 

LEFT JOIN comments c 
ON q.post_id = c.parent_post_id 

WHERE q.post_id = 10 
GROUP BY q.post_id 

Was erhalte ich:

[ 
    { 
    "post_id": "10", 
    "created_at": "2016-05-10T00:16:54.469Z", 
    "post_type": "question", 
    "post_title": "qwerty", 
    "post_text": "asdasd asda sdasd", 
    "post_author_id": 1, 
    "parent_post_id": null, 
    "is_accepted": null, 
    "acceptor_id": null, 
    "answers": [ 
     { 
     "post_id": 17, 
     "created_at": "2016-05-10T04:58:56.350229", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "222asda dasdad asdada", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 5, 
      "created_at": "2016-05-10T10:56:30.220128", 
      "text": "qweqwe", 
      "author_id": 1, 
      "parent_post_id": 17 
      }, 
      { 
      "id": 8, 
      "created_at": "2016-05-10T11:00:00.182991", 
      "text": "sasasd", 
      "author_id": 1, 
      "parent_post_id": 17 
      } 
     ] 
     }, 
     { 
     "post_id": 17, 
     "created_at": "2016-05-10T04:58:56.350229", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "222asda dasdad asdada", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 5, 
      "created_at": "2016-05-10T10:56:30.220128", 
      "text": "qweqwe", 
      "author_id": 1, 
      "parent_post_id": 17 
      }, 
      { 
      "id": 8, 
      "created_at": "2016-05-10T11:00:00.182991", 
      "text": "sasasd", 
      "author_id": 1, 
      "parent_post_id": 17 
      } 
     ] 
     }, 
     { 
     "post_id": 17, 
     "created_at": "2016-05-10T04:58:56.350229", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "222asda dasdad asdada", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 5, 
      "created_at": "2016-05-10T10:56:30.220128", 
      "text": "qweqwe", 
      "author_id": 1, 
      "parent_post_id": 17 
      }, 
      { 
      "id": 8, 
      "created_at": "2016-05-10T11:00:00.182991", 
      "text": "sasasd", 
      "author_id": 1, 
      "parent_post_id": 17 
      } 
     ] 
     }, 
     { 
     "post_id": 17, 
     "created_at": "2016-05-10T04:58:56.350229", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "222asda dasdad asdada", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 5, 
      "created_at": "2016-05-10T10:56:30.220128", 
      "text": "qweqwe", 
      "author_id": 1, 
      "parent_post_id": 17 
      }, 
      { 
      "id": 8, 
      "created_at": "2016-05-10T11:00:00.182991", 
      "text": "sasasd", 
      "author_id": 1, 
      "parent_post_id": 17 
      } 
     ] 
     }, 
     { 
     "post_id": 14, 
     "created_at": "2016-05-10T04:19:19.005556", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "asdasdasdasd", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 2, 
      "created_at": "2016-05-10T05:25:34.671008", 
      "text": "qeqweqwe", 
      "author_id": 1, 
      "parent_post_id": 14 
      } 
     ] 
     }, 
     { 
     "post_id": 14, 
     "created_at": "2016-05-10T04:19:19.005556", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "asdasdasdasd", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 2, 
      "created_at": "2016-05-10T05:25:34.671008", 
      "text": "qeqweqwe", 
      "author_id": 1, 
      "parent_post_id": 14 
      } 
     ] 
     }, 
     { 
     "post_id": 14, 
     "created_at": "2016-05-10T04:19:19.005556", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "asdasdasdasd", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 2, 
      "created_at": "2016-05-10T05:25:34.671008", 
      "text": "qeqweqwe", 
      "author_id": 1, 
      "parent_post_id": 14 
      } 
     ] 
     }, 
     { 
     "post_id": 14, 
     "created_at": "2016-05-10T04:19:19.005556", 
     "post_type": "answer", 
     "post_title": null, 
     "post_text": "asdasdasdasd", 
     "post_author_id": 1, 
     "parent_post_id": 10, 
     "is_accepted": null, 
     "acceptor_id": null, 
     "comments": [ 
      { 
      "id": 2, 
      "created_at": "2016-05-10T05:25:34.671008", 
      "text": "qeqweqwe", 
      "author_id": 1, 
      "parent_post_id": 14 
      } 
     ] 
     } 
    ], 
    "comments": [ 
     { 
     "id": 1, 
     "created_at": "2016-05-10T05:25:28.200327", 
     "text": "asadasdad", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 4, 
     "created_at": "2016-05-10T10:25:23.381177", 
     "text": "werwer", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 1, 
     "created_at": "2016-05-10T05:25:28.200327", 
     "text": "asadasdad", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 4, 
     "created_at": "2016-05-10T10:25:23.381177", 
     "text": "werwer", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 1, 
     "created_at": "2016-05-10T05:25:28.200327", 
     "text": "asadasdad", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 4, 
     "created_at": "2016-05-10T10:25:23.381177", 
     "text": "werwer", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 1, 
     "created_at": "2016-05-10T05:25:28.200327", 
     "text": "asadasdad", 
     "author_id": 1, 
     "parent_post_id": 10 
     }, 
     { 
     "id": 4, 
     "created_at": "2016-05-10T10:25:23.381177", 
     "text": "werwer", 
     "author_id": 1, 
     "parent_post_id": 10 
     } 
    ] 
    } 
] 

Antwort

1

Gruppierung geschieht, wenn alle Parteien verbunden worden sind, so Aggregate hängt von der resultierenden Kardinalität ab. Das Verbinden von Posts mit Antworten und Kommentaren bewirkt eine vollständige Verbindung zwischen ihnen und dupliziert alle Werte. Sie müssen einzeln getrennt und durchgeführt wird, ein, wie Sie es tun können, ist die folgende:

SELECT 
    q.*, 
    (SELECT json_agg(ac.*) 
    FROM (
     SELECT a.*, json_agg(c.*) AS comments 
     FROM posts a 
     LEFT JOIN comments c ON (a.post_id = c.parent_post_id) 
     WHERE a.parent_post_id = q.post_id 
     GROUP BY a.post_id 
     ) ac 
    ) AS answers, 
    json_agg(c.*) AS comments --comments on posts of post_id questions 
FROM posts q 
LEFT JOIN comments c ON (q.post_id = c.parent_post_id) 
WHERE q.post_id = 10 
GROUP BY q.post_id; 

Alternativ:

SELECT q.*, qa.answers, qc.comments 
FROM posts q 
LEFT JOIN (
    SELECT ac.parent_post_id, json_agg(ac.*) AS answers 
    FROM (
    SELECT ac.*, json_agg(c.*) AS comments 
    FROM posts ac 
    LEFT JOIN comments c ON (c.parent_post_id = ac.post_id) 
    GROUP BY ac.post_id 
    ) ac 
    GROUP BY ac.parent_post_id 
) qa ON (qa.parent_post_id = q.post_id) 
LEFT JOIN (
    SELECT c.parent_post_id, json_agg(c.*) AS comments 
    FROM comments c 
    GROUP BY c.parent_post_id 
) qc ON (qc.parent_post_id = q.post_id) 
WHERE q.post_id = 10; 
+0

ich zwei Fehlermeldungen aus diesen Abfragen an meinem Terminal. Der erste ist für den ersten: "[Fehler: Syntaxfehler bei oder nahe". "]" Und der zweite für letzterer: '[Fehler: Syntaxfehler bei oder nahe bei" VON "]'. Ich konnte den Grund nicht finden? Ich schaue nach, um es herauszufinden. –

+0

Von 'LINKER JOIN Kommentare c (q.post_id = c.parent_post_id)' meinst du 'LINKER JOIN Kommentare c ON q.post_id = c.parent_post_id' –

+0

@ Işık Ja, beide Fehler jetzt behoben –