4

我有三个包含书籍和标签的表格。一本书可以用多个标签进行标记。

我想要做的是过滤掉带有“漫画”和“浪漫”标签的书籍。

  1. 第一本书只标有“漫画”。
  2. 第二本书同时标记了“漫画”和“浪漫”,因此在我们的示例中应该返回这一行。
  3. 第三本书只标有“幻想”。

如何构建适当的查询来查找第二本书?

..select book_id from books b, tags t, tags_to_books tb where ((FIND TAGS_ID '7' AND '8'))..

表设计:

DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
  `book_id` int(11) NOT NULL AUTO_INCREMENT,
   PRIMARY KEY (`book_id`)
 );

 INSERT INTO `books` (`book_id`)
 VALUES
(1),
(2),
(3);

 DROP TABLE IF EXISTS `tags`;
 CREATE TABLE `tags` (
   `tag_id` int(11) NOT NULL AUTO_INCREMENT,
   `tag_name` varchar(11) NOT NULL DEFAULT '',
   PRIMARY KEY (`tag_id`)
 );

 INSERT INTO `tags` (`tag_id`, `tag_name`)
 VALUES
(7,'Comics'),
(8,'Romance'),
(9,'Fantasy');

 DROP TABLE IF EXISTS `tags_to_books`;
 CREATE TABLE `tags_to_books` (
   `book_id` int(11) NOT NULL,
   `tag_id` int(11) NOT NULL
 );

 INSERT INTO `tags_to_books` (`book_id`, `tag_id`)
 VALUES
(1,7),
(2,7),
(2,8),
(3,9);
4

5 回答 5

2

您可以使用类似这样的东西,这实际上与其他 SQL 语言中的交集运算符相同:

select comics.book_id from (
select b.book_id
  from books b
  join tags_to_books tb on tb.book_id = b.book_id
  join tags t on tb.tag_id = t.tag_id
  where t.tag_id = 7) as comics
join (
select b.book_id
  from books b
  join tags_to_books tb on tb.book_id = b.book_id
  join tags t on tb.tag_id = t.tag_id
  where t.tag_id = 8) as romance
on comics.book_id = romance.book_id

这可能会被优化一点,但想法是获取所有幻想中的书籍,然后是浪漫中的所有书籍,然后返回两者中的书籍。如果您需要在需要更多条件的地方创建查询,只需复制 JOIN 子句并更新标签 ID。

链接到 SQL 小提琴

于 2013-08-15T14:32:51.940 回答
1

If I understand you correctly, the same book can appear in the tag table multiple times. Correct?

Have you tried something like

SELECT book_id
FROM books
WHERE book_id NOT IN 
    (SELECT comics.book_id
    FROM tags_to_books as comics
    JOIN tags_to_books as romance
      ON comics.book_id = romance.book_id
    WHERE comics.tag_id = 7
      AND romance.tag_id = 8)

?

于 2013-08-15T14:24:56.077 回答
0

很难阅读,但是:

SELECT B.book_id
FROM Books B INNER JOIN tags_to_books ttb
ON ttb.book_ID = b.book_ID
JOIN tags t
ON t.tag_ID = ttb.Tag_ID
WHERE t.tag_ID IN(7) AND t.tag_ID IN(8)

我还没有编译这个,但它应该可以工作

或者正如乔所描述的,你可以通过 tag_name 来做到这一点

SELECT B.book_id
FROM Books B INNER JOIN tags_to_books ttb
ON ttb.book_ID = b.book_ID
JOIN tags t
ON t.tag_ID = ttb.Tag_ID
WHERE t.tag_name = 'Comics' AND t.tag_name = 'Romance'
于 2013-08-15T14:22:13.997 回答
0

如果您只需要book_id(而不是书名或标签文本,则可以使用(但如果您的查询中有不同数量的标签,则需要更改下面描述的幻数):

SELECT book_id FROM tags_to_books
WHERE tag_id IN (7, 8)
GROUP BY book_id
HAVING COUNT(DISTINCT book_id, tag_id) = 2;

2是标签的数量,如果您的查询中有更多或更少的标签,您必须更改它。

于 2013-08-15T14:23:06.637 回答
0

这是 sql:http ://sqlfiddle.com/#!2/fc556/6 希望这会有所帮助

于 2013-08-15T14:23:28.767 回答