【问题标题】:Many to many tables combine in arrays多对多表组合成数组
【发布时间】:2019-08-07 11:26:52
【问题描述】:

我如何选择这种格式的书:

{
   title: 'Avengers', 
   description:'Good book', 
   tags: [{id:1, name: 'Drama'},{id:2, name: 'Horror'}]
   authors: [{id:1, name: 'Alex'},{id:2, name: 'Tanya'}]
}

对于具有多对多关系的表:

或者最好创建 3 个不同的 pool.requests?

书籍

|id|title     |description|
|1 |'Avengers'|'Good book'|
|2 |'Fear'    |'Scary'

作者

|id|name
|1 |'Alex'
|2 |'Tanya'

authors_books

|book_id|author_id
|1      |1
|1      |2
|2      |1

标签

|id|name
|1 |'Drama'
|2 |'Horror'

tags_books

|book_id|tag_id
|1      |1
|1      |2
|2      |1

我以前用过这个没有作者表:

SELECT b.title, b.id, b.description,
 json_agg(json_build_object('id', t.id, 'name', t.name, 'description', 
 t.description, 'likes', tb.likes) ORDER BY tb.likes DESC) AS tags
 FROM books AS b
 INNER JOIN tags_books AS tb ON (b.id = tb.book_id)
 INNER JOIN tags AS t ON (tb.tag_id = t.id)
 WHERE b.id = $1
 GROUP BY b.id;`

但是对于表 autors 使用新的 INNER JOIN,将会有重复的值。

【问题讨论】:

    标签: arrays json postgresql aggregate-functions jsonb


    【解决方案1】:

    您应该在不同的派生表(FROM 子句中的子查询)中聚合数据(authorstags):

    select 
        b.title, 
        b.description,
        t.tags, 
        a.authors
    from books as b
    join (
        select 
            tb.book_id,
            json_agg(json_build_object('id', t.id, 'name', t.name) order by tb.likes desc) as tags
        from tags_books as tb
        join tags as t on tb.tag_id = t.id
        group by tb.book_id
        ) t on b.id = t.book_id
    join (
        select 
            ab.book_id,
            json_agg(json_build_object('id', a.id, 'name', a.name) order by ab.author_id) as authors
        from authors_books as ab
        join authors as a on ab.author_id = a.id
        group by ab.book_id
        ) a on b.id = a.book_id
    
      title   | description |                             tags                              |                           authors                           
    ----------+-------------+---------------------------------------------------------------+-------------------------------------------------------------
     Avengers | Good book   | [{"id" : 2, "name" : "Horror"}, {"id" : 1, "name" : "Drama"}] | [{"id" : 1, "name" : "Alex"}, {"id" : 2, "name" : "Tanya"}]
     Fear     | Scary       | [{"id" : 1, "name" : "Drama"}]                                | [{"id" : 1, "name" : "Alex"}]
    (2 rows)
    

    【讨论】:

    • 但是你认为加入 json_agg 和 json_build_object 会比单独的请求更好吗?
    • 一般规则是,在连接之前聚合派生表中的数据比聚合连接表上的数据更快(或至少不慢),因为该操作是在较小的数据集上执行的。此外,单个查询(使用派生表)比两个单独的查询更好(除非它在非常大的表上执行)。
    猜你喜欢
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 2021-09-14
    • 2019-12-19
    • 1970-01-01
    相关资源
    最近更新 更多