我正在尝试构建一个查询,其中包含一个指示用户是否已下载文档的列。我有一个名为 HasDownloaded 的表,其中包含以下列:id、文档 ID、会员 ID。查明用户是否下载过 具体的 文档很简单;但我需要生成一个查询,其结果如下所示:

name              id
----------------------
abc               NULL
bbb               2
ccc               53
ddd               NULL
eee               13

ID其实并不重要;重要的是。我感兴趣的是文档是否已下载(是否为NULL)。

这是我的查询:

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id
WHERE HasDownloaded.memberID = @memberID

问题是,只有当 HasDownloaded 表中存在指定用户的条目时,这才会返回值。我想保持简单,并且仅在 HasDownloaded 中包含以下文档的条目: 已下载。因此,如果用户 1 已经下载了 abc、bbb 和 ccc,我仍然希望 ddd 和 eee 显示在结果表中,只是 id 为 NULL。但 WHERE 子句只给出存在条目的值。

我不是一个 SQL 专家 - 有没有一个运算符可以给我我想要的东西?我应该采取不同的方法吗?或者这是不可能的?

有帮助吗?

解决方案

将WHERE子句中的条件移动到连接条件。

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id 
  AND HasDownloaded.memberID = @memberID 

只要您想在WHERE子句中引用左连接表,就必须这样做。

其他提示

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId

将是正常的方式。有些人会把它缩短为:

WHERE COALESCE(HasDownloaded.memberId, @memberId) = @memberId

你可以像Matt B.所示,在你的JOIN条件下做到这一点 - 但我认为这更容易让人混淆。如果你不明白为什么将它移动到JOIN条款有效,那么我强烈建议远离它。

@标记:我明白为什么 JOIN 语法有效,但感谢您的警告。我确实认为你的建议更直观。我很好奇哪个更有效率。所以我进行了一个快速测试(恐怕这相当简单,只有 14 行和 10 次试验):

在 JOIN 条件下:

AND HasDownloaded.memberID = @memberID
  • 客户处理时间:4.6
  • 总执行时间:35.5
  • 等待服务器回复的时间:30.9

在 WHERE 子句中:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • 客户处理时间:7.7
  • 总执行时间:27.7
  • 等待服务器回复的时间:22.0

看起来 WHERE 子句的效率稍微高一些。有趣的!再次感谢你们俩的帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top