我有一个像这样的表
书籍:
id | title | rating_avr | visible
1 | 'Overlord' | 5 | true
2 | 'Avengers' | 10 | false
tags_books:
tag_id | book_id | likes
1 | 1 | 5
2 | 1 | 25
1 | 2 | 11
标签:
id | name
1 | 'Adventure'
2 | 'Drama'
现在,我需要加载带有LIMIT,ORDER和标记标签的书籍“ Drama”的书籍。
我设法通过查询实现了这一点:
SELECT b.id, b.title, b.rating_avr, json_agg(json_build_object('id', tb2.tag_id)) as tags
FROM books b
LEFT JOIN tags_books tb ON tb.book_id = b.id
LEFT JOIN tags_books tb2 ON tb2.book_id = b.id
WHERE tb.tag_id = 1 AND b.visible=true
GROUP BY b.id ORDER BY b.rating_avr DESC LIMIT 5
我很好奇:
1)可以将同一张桌子连接两次吗?第一个用于where子句,第二个用于聚集标签。
2)如何根据喜欢点排序聚合标签?
3)这是正确的方法,还是有更好的方法?
答案 0 :(得分:1)
奇怪的是,在查询中您没有使用表tags
,尽管您想获取标签'Drama'
的书,该标签是表tags
中的一列。
我要做的是首先使用类似的查询获取所有标签为'Drama'
的书籍的ID:
SELECT b.id FROM books b
INNER JOIN tags_books tb ON tb.book_id = b.id
INNER JOIN tags t ON t.id = tb.tag_id
WHERE t.name = 'Drama' AND b.visible=true
然后使用它来获得结果:
SELECT
b.id, b.title, b.rating_avr,
json_agg(json_build_object('id', tb.tag_id) order by tb.likes desc) as tags
FROM books b INNER JOIN tags_books tb
ON tb.book_id = b.id
WHERE b.id IN (
SELECT b.id FROM books b
INNER JOIN tags_books tb ON tb.book_id = b.id
INNER JOIN tags t ON t.id = tb.tag_id
WHERE t.name = 'Drama' AND b.visible=true
)
GROUP BY b.id, b.title, b.rating_avr
ORDER BY b.rating_avr DESC LIMIT 5
请参见demo。
结果:
> id | title | rating_avr | tags
> -: | :------- | ---------: | :-----------------------
> 1 | Overlord | 5 | [{"id" : 2}, {"id" : 1}]