MS Access SQL - 从 5 个表中搜索
MS Access SQL - Searching from 5 tables
我有一个存储电子书信息的数据库,它由 5 个表组成,即
- BOOKS (book_id, book_name, book_rating)
- AUTHORS (author_id, author_name)
- BOOK_AND_AUTHORS (ba_id, book_id, author_id)
- TAGS (tag_id, tag_name)
- BOOKS_AND_TAGS (bt_id, book_id, tag_id)
每本书都有一个或多个作者和一个或多个标签(对它们进行分类)。 BOOKS_AND_AUTHORS
和 BOOKS_AND_TAGS
是联结表,用于维护 book:authors 和 books:tags 之间的多对多关系。
现在我想做的是使用多个条件搜索具有 sql 的特定书籍。
例如,我想获取满足以下条件的图书的名称和 ID,
- Has a rating of 2 or above
- Should only have the tags denoted by tag id's 2 and 219; no other tags allowed.
我的解决方案包括以下内容。
SELECT DISTINCT books.book_id, books.book_name
FROM
(
(tags INNER JOIN books_and_tags ON tags.tag_id = books_and_tags.tag_id)
INNER JOIN
(books INNER JOIN
(authors INNER JOIN books_and_authors
ON authors.author_id = books_and_authors.author_id)
ON books.book_id = books_and_authors.book_id)
ON books_and_tags.book_id = books.book_id
)
WHERE ((BOOKS.book_rating >= 2) AND ((TAGS.tag_id) IN (2,219)))
GROUP BY BOOKS.book_id, BOOKS.book_name
HAVING COUNT(TAGS.tag_id) = 2
不幸的是,这不是 return 我想要的。我做错了吗?关于如何使用 SQL 实现此类搜索的任何建议?谢谢。
在网上搜索了一下,找到了解决方法。
问题是由五个 table 连接和 SQL 语句的以下部分产生的:
WHERE ((BOOKS.book_rating >= 2) AND ((TAGS.tag_id) IN (2,219)))
GROUP BY BOOKS.book_id, BOOKS.book_name
HAVING COUNT(TAGS.tag_id) = 2
加入五个 table 之后,对于某些预期情况,COUNT(TAGS.tag_id) = 2
不会被评估为 TRUE。这是因为在连接操作生成的结果集中,包含给定书籍的许多重复行。因此,COUNT...
部分在某些情况下会失败。为了克服这个问题,COUNT 应该只考虑不同的 tag_id。解决方案应该是这样的,
HAVING COUNT (DISTINCT TAGS.tag_id) = 2
如果只有 MS Access SQL 引擎支持 DISTINCT
聚合函数。请参阅此以获取更多信息:How do I count unique items in field in Access query?
因此,我最终的解决方案是:
SELECT DISTINCT books.book_id, books.book_name
FROM
(SELECT DISTINCT tags.tag_id, books.book_id, books.book_name
FROM (
(tags INNER JOIN books_and_tags ON tags.tag_id = books_and_tags.tag_id)
INNER JOIN
(books INNER JOIN
(authors INNER JOIN books_and_authors
ON authors.author_id = books_and_authors.author_id)
ON books.book_id = books_and_authors.book_id)
ON books_and_tags.book_id = books.book_id
) WHERE (BOOKS.book_rating >= 2) [+ all the other conditions NOT based on tags]
)
WHERE (TAGS.tag_id) IN (2,219)
GROUP BY BOOKS.book_id, BOOKS.book_name
HAVING COUNT(TAGS.tag_id) = 2
请注意,原来的 WHERE
子句已拆分为两个。
我有一个存储电子书信息的数据库,它由 5 个表组成,即
- BOOKS (book_id, book_name, book_rating)
- AUTHORS (author_id, author_name)
- BOOK_AND_AUTHORS (ba_id, book_id, author_id)
- TAGS (tag_id, tag_name)
- BOOKS_AND_TAGS (bt_id, book_id, tag_id)
每本书都有一个或多个作者和一个或多个标签(对它们进行分类)。 BOOKS_AND_AUTHORS
和 BOOKS_AND_TAGS
是联结表,用于维护 book:authors 和 books:tags 之间的多对多关系。
现在我想做的是使用多个条件搜索具有 sql 的特定书籍。
例如,我想获取满足以下条件的图书的名称和 ID,
- Has a rating of 2 or above
- Should only have the tags denoted by tag id's 2 and 219; no other tags allowed.
我的解决方案包括以下内容。
SELECT DISTINCT books.book_id, books.book_name
FROM
(
(tags INNER JOIN books_and_tags ON tags.tag_id = books_and_tags.tag_id)
INNER JOIN
(books INNER JOIN
(authors INNER JOIN books_and_authors
ON authors.author_id = books_and_authors.author_id)
ON books.book_id = books_and_authors.book_id)
ON books_and_tags.book_id = books.book_id
)
WHERE ((BOOKS.book_rating >= 2) AND ((TAGS.tag_id) IN (2,219)))
GROUP BY BOOKS.book_id, BOOKS.book_name
HAVING COUNT(TAGS.tag_id) = 2
不幸的是,这不是 return 我想要的。我做错了吗?关于如何使用 SQL 实现此类搜索的任何建议?谢谢。
在网上搜索了一下,找到了解决方法。
问题是由五个 table 连接和 SQL 语句的以下部分产生的:
WHERE ((BOOKS.book_rating >= 2) AND ((TAGS.tag_id) IN (2,219)))
GROUP BY BOOKS.book_id, BOOKS.book_name
HAVING COUNT(TAGS.tag_id) = 2
加入五个 table 之后,对于某些预期情况,COUNT(TAGS.tag_id) = 2
不会被评估为 TRUE。这是因为在连接操作生成的结果集中,包含给定书籍的许多重复行。因此,COUNT...
部分在某些情况下会失败。为了克服这个问题,COUNT 应该只考虑不同的 tag_id。解决方案应该是这样的,
HAVING COUNT (DISTINCT TAGS.tag_id) = 2
如果只有 MS Access SQL 引擎支持 DISTINCT
聚合函数。请参阅此以获取更多信息:How do I count unique items in field in Access query?
因此,我最终的解决方案是:
SELECT DISTINCT books.book_id, books.book_name
FROM
(SELECT DISTINCT tags.tag_id, books.book_id, books.book_name
FROM (
(tags INNER JOIN books_and_tags ON tags.tag_id = books_and_tags.tag_id)
INNER JOIN
(books INNER JOIN
(authors INNER JOIN books_and_authors
ON authors.author_id = books_and_authors.author_id)
ON books.book_id = books_and_authors.book_id)
ON books_and_tags.book_id = books.book_id
) WHERE (BOOKS.book_rating >= 2) [+ all the other conditions NOT based on tags]
)
WHERE (TAGS.tag_id) IN (2,219)
GROUP BY BOOKS.book_id, BOOKS.book_name
HAVING COUNT(TAGS.tag_id) = 2
请注意,原来的 WHERE
子句已拆分为两个。