我的MySQL数据库中有两个表,一个是数据库中所有书籍的库,另一个是包含与用户库中书籍相对应的各个行。
例如:
图书馆表
`id` `title`...
===== ===========
1 Moby Dick
2 Harry Potter
收集表
`id` `user` `book`
===== ====== =======
1 1 2
2 2 2
3 1 1
我想要做的是运行一个查询,该查询将显示用户集合中不的所有书籍。我可以运行此查询以显示不在任何用户的集合中的所有书籍:
SELECT *
FROM `library`
LEFT OUTER JOIN `collection` ON `library`.`id` = `collection`.`book`
WHERE `collection`.`book` IS NULL
据我所知,这很好用。在PHPMyAdmin中运行它将导致所有不在集合表中的书籍。
但是,如何将其限制为某个用户?例如,使用上面的虚拟数据,如果用户2
运行查询,我希望书1结果,如果用户1
运行查询,则不需要书籍。
添加AND user=[id]
不起作用,而且我对JOIN
语句的知识非常有限,我实际上并没有得到任何结论。
此外,返回的结果的ID(显示的查询,不执行我想要但功能正常)为0 - 如何确保返回的ID是library.id
的ID?
答案 0 :(得分:13)
您必须将LEFT JOIN
选择范围缩小到只有特定用户拥有的图书,然后联接表中NULL
的任何内容都是行(用户在他/她的收藏中没有的书籍:
SELECT
a.id,
a.title
FROM
library a
LEFT JOIN
(
SELECT book
FROM collection
WHERE user = <userid>
) b ON a.id = b.book
WHERE
b.book IS NULL
另一种选择是:
SELECT
a.id,
a.title
FROM
library a
WHERE
a.id NOT IN
(
SELECT book
FROM collection
WHERE user = <userid>
)
然而,第一个解决方案更优化,因为MySQL将为每一行执行一次NOT IN
子查询,而不是仅对整个查询执行一次。直观地说,你会期望MySQL一次执行子查询并将其用作列表,但MySQL不够聪明,无法区分相关子查询和非相关子查询。
如上所述here:
“问题是,对于使用IN子查询的语句, 优化器将其重写为相关子查询。“
答案 1 :(得分:3)
这个怎么样?它只是我的头脑 - 我现在无法访问数据库进行测试。 (对不起)
SELECT
*
FROM
library lib
WHERE
lib.id NOT IN (
SELECT
book
FROM
collection coll
WHERE
coll.user =[id]
)
;