我必须通过标签定义book的属性,我正在考虑创建表
Table Books
Book_Id INT, PK
Book_Name varchar
Table Tags
Tag_Id INT, PK
Tag_Name varchar
一本书可以有多个标签,如恐怖,搞笑,黑暗等。我如何定义一本书及其所有标签之间的一对多关系?
答案 0 :(得分:2)
您需要在书籍和标签之间创建一个连接表,如下所示:
Books_Tags Table
Book_id int -- will be PK
Tag_ig int -- will be PK
连接表的主键将包含两个字段(book_id
和tag_id
),这两个字段也是其他表的外键。
然后,当您要查询数据时,您的查询将与此类似:
select *
from books b
left join books_tags bt
on b.book_id = bt.bookid
left join tags t
on bt.tag_id = t.tag_id
答案 1 :(得分:2)
考虑使用自然键(而不是代理“标签ID”)来避免在搜索标签时可能需要的JOIN之一(这可能是合理大小的数据库上的性能关键路径)。
例如:
CREATE TABLE BOOK (
BOOK_ID INT PRIMARY KEY
-- Other fields...
);
CREATE TABLE BOOK_TAG (
TAG_NAME VARCHAR(30),
BOOK_ID INT,
PRIMARY KEY (TAG_NAME, BOOK_ID),
FOREIGN KEY (BOOK_ID) REFERENCES BOOK (BOOK_ID) ON DELETE CASCADE
);
-- For enforcing and cascading the FK and for GROUP BY (in the query below).
CREATE INDEX BOOK_TAG_IE1 ON BOOK_TAG (BOOK_ID, TAG_NAME);
CREATE TABLE TAG (
TAG_NAME VARCHAR(30) PRIMARY KEY,
-- Other fields...
);
您现在可以获得具有任何给定标签的图书,如下所示:
SELECT *
FROM BOOK
WHERE BOOK_ID IN (
SELECT BOOK_ID
FROM BOOK_TAG
WHERE
TAG_NAME = 'tag1'
OR TAG_NAME = 'tag2'
-- Etc...
);
具有全部给定标签的图书如下:
SELECT *
FROM BOOK
WHERE BOOK_ID IN (
SELECT BOOK_ID
FROM BOOK_TAG
WHERE
TAG_NAME = 'tag1'
OR TAG_NAME = 'tag2'
-- Etc...
GROUP BY BOOK_ID
HAVING COUNT(TAG_NAME) = 2
);
如您所见,只有一个JOIN(在此处写为IN)。在搜索图书时(或只显示标签名称 - 此处未显示),根本不需要使用TAG表加入。
进行第二次JOIN的唯一原因是,当你需要从TAG表中获取这些“其他字段”时。
答案 2 :(得分:0)
我会制作第3张桌子并制作Book>标记多对多的关系。
所以:
表书 Book_Id INT,PK Book_Name varchar
表格标签 Tag_Id INT,PK Tag_Name varchar
Table BookTags Id INT,PK Book_Id INT Tag_Id Int