2016-05-11 4 views
1

У меня есть три таблицы сообщений, комментариев и пользователей. стол переговоров включает в себя два типа должностей, вопрос и ответ. Комментарии сделаны по вопросам и ответам. Моя цель - получить один вопрос с комментариями по нему, ответы на него и комментарии к этим ответам. Также мне нужно имя пользователя из таблицы пользователей как автора по каждому вопросу, ответам и комментариям, которые я получаю. Я использую Postgres 9.5 и пользуюсь функцией json_agg().Повторяющиеся записей в SQL JOIN запроса

В то время как пример вывода Мне нужно что-то похожее на первое, я получаю повторяющиеся записи.

Что мне здесь не хватает? Возможны правильные групповые предложения. Или подзапрос для сбора ответов с их комментариями - это не способ сделать это. Когда я комментирую левое соединение с сообщениями в таблице комментариев, я получаю желаемые результаты без комментариев по вопросам. Также, когда я отменяю левое соединение, содержащее подзапрос, я получаю не повторяющиеся результаты, как я ожидаю, и снова это не полный набор данных, который я желаю. Это вещи, которые я собрал до сих пор, чтобы решить мою проблему.

Что мне нужно:

[ 
    { 
    "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 
     } 
    ] 
    } 
] 

Мой запрос:

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 

Что я получаю:

[ 
    { 
    "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 
     } 
    ] 
    } 
] 

ответ

1

Группировка происходит после того, все стороны были объединены, так агрегатов будет зависеть от итоговой мощности. Присоединение сообщений с ответами и комментариями приводит к полному соединению между ними, дублируя все значения. Они должны быть разделены и выполняются индивидуально, один из способов вы можете сделать это состоит в следующем:

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; 

В качестве альтернативы:

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

Я получаю два сообщения об ошибках из этих запросов на моем терминале. Первый для первого: '[ошибка: синтаксическая ошибка в или рядом". "]', А ​​вторая для последней: '[ошибка: синтаксическая ошибка в или рядом с" FROM "]'. Я не мог найти почему? Я продолжаю проверять, чтобы понять. –

+0

По 'LEFT JOIN comments c (q.post_id = c.parent_post_id)' вы имели в виду 'LEFT JOIN comments c ON q.post_id = c.parent_post_id' –

+0

@ Işık Да, исправлены оба ошибки сейчас –