2008-10-20 77 views
17

我试图构造一个查询,它将包含一个指示用户是否下载了文档的列。我有一个名为HasDownloaded的表,其中包含以下列:id,documentID,memberID。查明用户是否已下载特定的文档很容易;但我需要生成一个查询,其结果如下所示:LEFT JOIN上的WHERE帮助SQL查询

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专家 - 是否有一个运营商会给我我想要的东西?我应该采取不同的方法吗?或者这是不可能的?

回答

35

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

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

这是必要的,只要你想引用一个左连接ed表,否则会是WHERE子句。

+1

非常好!这就是我一直在寻找的。 – ine 2008-10-20 16:30:31

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

将是正常的方式来做到这一点。有些人会缩短到:

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

可以,马特B.表明,这样做在你的JOIN条件 - 但我认为这是更容易迷惑人。如果你不明白为什么将它移到JOIN子句的作用,那么我强烈建议远离它。

3

@Mark:我明白为什么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子句一样稍微高效。有趣!再一次感谢你们两位的帮助。