如何列出不存在的项目?

时间:2010-03-03 21:33:15

标签: sql mysql

标题可能有点令人困惑,让我解释一下,;) 我有3张桌子:

[names]
n_id;name
1;Jeff
2;Adam

[books]
b_id;title
1;Book1
2;Book2

[read]
n_id;b_id

表格[读取]是一本包含阅读书籍的表格。 如果Adam读“Book1”,[read]中的项目如下所示:

2;1
到目前为止,这么好。 现在,有没有办法知道一个人没有读过哪些书? 我们知道只有亚当读了一本书“Book1”,所以查询应该输出这样的东西:

n_id;name;b_id;title
1;Jeff;1;Book1
1;Jeff;2;Book2
2;Adam;2;Book2

是否可以在1个查询中执行此操作,还是需要一些脚本?

4 个答案:

答案 0 :(得分:2)

您可以使用CROSS JOIN获取namesbooks的所有可能组合,然后使用read IS NULL LEFT JOIN NULL删除那里存在的行。

r.n_id IS NULL为没有行的所有已加入列返回read,因此请检查SELECT n.n_id, n.name, b.b_id, b.title FROM names n CROSS JOIN books b LEFT JOIN read r ON ( r.n_id = n.n_id AND r.b_id = b.b_id ) WHERE r.n_id IS NULL 是否删除了{{1}}中连接实际找到行的那些行。

{{1}}

答案 1 :(得分:1)

您需要一个交叉联接来生成所有name vs book对,然后加入read表并检查加入失败的位置。

SELECT names.n_id, names.name, books.b_id, books.title
FROM names
CROSS JOIN books 
LEFT JOIN read
ON names.n_id = read.n_id AND books.b_id = read.b_id
WHERE read.n_id IS NULL

答案 2 :(得分:1)

您可以在名称和书籍之间进行笛卡尔联接以获取所有可能的名称/书籍组合,然后减去已阅读的名称/书籍组合:

SELECT n_id, b_id
FROM names, books
MINUS
SELECT n_id, b_id
FROM read

其他人建议进行交叉连接和左连接,这也可以很好地工作。可能想要尝试两者看看哪个在现实场景中更快 - 我怀疑左边加入其他建议会更快,但不是很确定。

答案 3 :(得分:0)

你的问题是,“有没有办法知道一个的人没看过哪些书?”但是你的样本查询结果显示了问题的答案,“有没有办法知道所有人都没有读过哪些书?”

如果你真的只想为特定的人运行查询,那么这样的事情应该有效:

SELECT b_id, title
FROM books  --You said you're just looking for books
WHERE b_id NOT IN
  (SELECT b_id
   FROM read
   WHERE n_id = @names_id) --pass in the names_id as a parameter