Arrays 多对多表组合成数组
如何选择此格式的书籍:Arrays 多对多表组合成数组,arrays,json,postgresql,aggregate-functions,jsonb,Arrays,Json,Postgresql,Aggregate Functions,Jsonb,如何选择此格式的书籍: { title: 'Avengers', description:'Good book', tags: [{id:1, name: 'Drama'},{id:2, name: 'Horror'}] authors: [{id:1, name: 'Alex'},{id:2, name: 'Tanya'}] } 对于具有多对多关系的表: 或者最好是提出3个不同的池请求 书 作者 |id|name |1 |'Alex' |2 |'Tanya' 作
{
title: 'Avengers',
description:'Good book',
tags: [{id:1, name: 'Drama'},{id:2, name: 'Horror'}]
authors: [{id:1, name: 'Alex'},{id:2, name: 'Tanya'}]
}
对于具有多对多关系的表:
或者最好是提出3个不同的池请求
书
作者
|id|name
|1 |'Alex'
|2 |'Tanya'
作家与书籍
|book_id|author_id
|1 |1
|1 |2
|2 |1
标签
标签和书籍
|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;`
但是,对于表autor的新内部联接,将有重复的值。您应该将数据(
作者
和标记
)聚合到单独的派生表中(在FROM
子句中的子查询):
但是,您认为使用json_agg和json_build_对象进行联接会比单独请求更好吗?一般规则是,在联接之前在派生表中聚合数据比在联接表上聚合数据更快(或至少不慢),因为该操作是在较小的数据集上执行的。此外,单个查询(使用派生表)比两个单独的查询(除非在非常大的表上执行)更好。
|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;`
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)