【问题标题】:Help with a WHERE on a LEFT JOIN SQL Query关于 LEFT JOIN SQL 查询的 WHERE 帮助
【发布时间】:2010-09-18 03:45:42
【问题描述】:

我正在尝试构建一个查询,该查询将包含一列,指示用户是否已下载文档。我有一个名为 HasDownloaded 的表,其中包含以下列:id、documentID、memberID。找出用户是否下载了特定文档很容易;但我需要生成一个查询,结果如下所示:

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 专家 - 有没有一个操作员可以在这里给我想要的东西?我应该采取不同的方法吗?或者这是不可能的?

【问题讨论】:

    标签: sql join left-join


    【解决方案1】:

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

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

    当您想在 WHERE 子句中引用左连接表时,这是必需的。

    【讨论】:

    【解决方案2】:
    WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
    

    这是正常的做法。有些人会将其缩短为:

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

    正如 Matt 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 子句的效率稍微高了一点。有趣的!再次感谢你们两位的帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多