我有一个代表书籍收藏的数据库。它看起来像这样:
id | title | year | author_id
--------------------------------------------------------
1 How to Read 1985 7
2 A Dream of Spring 2041 14
3 Tour Guide 2010 40
id | tagname
-------------------
1 nonfiction
2 fiction
3 poetry
4 sci-fi
5 magical realism
6 detective
book | tag
------------------
8 4
10 1
10 4
10 5
8 2
书籍和标签之间存在一对多的关系:一本书可以有多个标签,如“小说,侦探,科幻”。
我想知道的是:我是否可以在一个查询中选择所有书籍和与每本书相关的所有标签?我不知道结果会是什么样的 - 我想,这是一个锯齿状的数组,每本书都有不同数量的标签?
我的最终目标是输出一个HTML表格,其中每一行都是一本书,tr
元素的每个标签都有一个data-tag
属性,因此我可以使用JavaScript隐藏或显示带有某些标签组合的书籍。到目前为止,我只能想象如何通过为列表中的每本书发出单独的select tags
查询来做到这一点,但这可能意味着要生成数千个数据库请求,我想知道是否有更聪明的方法来执行此操作
我目前正在使用SQLite,但如果有Postgres或MySQL独有的解决方案,我仍然有兴趣了解它。
答案 0 :(得分:3)
在MySQL中,group_concat()
可能会做你想要的:
select b.*,
group_concat(t.tagname)
from books b join
book_tags bt
on b.id = bt.book join
tags t
on bt.tag = t.id
group by b.id;
这会将标记放在以逗号分隔的列表中,这可能是一个很好的格式。您可以使用SEPARATOR
关键字更改分隔符。
答案 1 :(得分:2)
在Postgres中,您应该使用array_agg()
功能来汇总链接到图书的标签。
select title, array_agg(tagname)
from books b
join books_tags_links l on l.book = b.id
join tags t on l.tag = t.id
group by 1
在SQLite3中你有一个类似的函数group_concat()
(array_agg()
返回一个数组group_concat()
- 一个字符串)。