【问题标题】:Nested json_agg嵌套的 json_agg
【发布时间】:2020-10-17 13:10:02
【问题描述】:

我有这个 postgresql 查询,它返回一个 json,其中包含所有书名、作者的名字和姓氏以及所有评论标题的数组 + 评论者的名字和姓氏。

SELECT json_build_object(
    'title', a.title,
    'author_firstname', b.firstname,
    'author_lastname', b.lastname,
    'reviews', json_agg(json_build_object(
        'review_title', c.title,
        'reviewer_firstname', d.firstname,
        'reviewer_lastname', d.lastname
    ))
)
FROM book AS a
INNER JOIN person AS b ON a.author_id = b.id
    LEFT JOIN review AS c ON c.book_id = a.id
    INNER JOIN person AS d ON c.reviewer_id = d.id
GROUP BY a.id, b.id

这很有效,而且速度很快。我还需要扩展此查询以包括审稿人书籍的所有标题。

我遵循了我用于第一个左连接的逻辑

SELECT json_build_object(
    'title', a.title,
    'author_firstname', b.firstname,
    'author_lastname', b.lastname,
    'reviews', json_agg(json_build_object(
        'review_title', c.title,
        'reviewer_firstname', d.firstname,
        'reviewer_lastname', d.lastname,
        'reviewer_books', json_agg(json_build_object(
            'book_title', e.title
        ))
    ))
)
FROM book AS a
INNER JOIN person AS b ON a.author_id = b.id
    LEFT JOIN review AS c ON c.book_id = a.id
    INNER JOIN person AS d ON c.reviewer_id = d.id
        LEFT JOIN book AS e ON e.author_id = d.id
GROUP BY a.id, b.id

但这不起作用,因为aggregate function calls cannot be nested。有没有办法解决这个问题,可以扩展到包括更深层次的关系(就像审稿人所有书籍的所有评论一样)并且相对高效。

那些数据库让我很困惑,所以谢谢你的帮助!

【问题讨论】:

  • 使用任意字母作为表别名是一种非常糟糕的做法。表名应使用缩写,例如b 代表bookp 代表person

标签: sql json postgresql


【解决方案1】:

您需要多个级别的聚合。这类似于:

SELECT json_build_object(
    'title', b.title,
    'author_firstname', p.firstname,
    'author_lastname', p.lastname,
    r.reviews
)
FROM book b INNER JOIN
     person p
     ON b.author_id = pb.id LEFT JOIN
     (SELECT r.book_id,
             json_agg(json_build_object('review_title', r.title,
                                        'reviewer_firstname', pr.firstname,
                                        'reviewer_lastname', pr.lastname,
                                        'reviewer_books', rb.reviewer_books
                                       )
                     ) as reviews
      FROM review r JOIN
           person pr
           on r.reviewer_id = pr.id JOIN
           (SELECT r2.reviewer_id, json_agg(json_build_object('book_title', b2.title) as reviewer_books
            FROM reviews r2 JOIN
                 book b2
                 ON r2.book_id = b2.id
            GROUP BY r2.reviewer_id
           ) rb
           on r.reviewer_id = rb.reviewer_id
    ) r
    on r.book_id = b.id;

【讨论】:

    猜你喜欢
    • 2021-05-22
    • 1970-01-01
    • 2017-09-13
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 2018-11-01
    相关资源
    最近更新 更多