LEFT JOIN 不返回 MS Access 左表中的所有行?

Posted

技术标签:

【中文标题】LEFT JOIN 不返回 MS Access 左表中的所有行?【英文标题】:LEFT JOIN in not returning full rows from left table in MS Access? 【发布时间】:2011-04-17 14:03:14 【问题描述】:
Testcases table
---------------
ID Testcase
1  TC-1
2  TC-5
3  TC-8

Tests table
-----------
ID TestCaseID Result Release
1  1          OK     1.1.111
2  3          FAIL   1.1.111

我想得到的是

Testcase Result
TC-1     OK
TC-5     <empty>
TC-8     FAIL

我得到的是

Testcase Result
TC-1     OK
TC-8     FAIL

查询:

SELECT Testcases.Testcase, Tests.Result
FROM Testcases LEFT JOIN Tests ON Testcases.ID=Tests.TestCaseID
WHERE Tests.Release="1.1.111";

【问题讨论】:

【参考方案1】:

有两种(微妙的)不同的方法可以做到这一点:

SELECT Testcases.Testcase
     , Tests.Result
FROM Testcases
  LEFT JOIN Tests
    ON (  ( Testcases.ID = Tests.TestCaseID )
      AND ( Tests.Release = "1.1.111" )
       )

和:

SELECT Testcases.Testcase
     , Tests.Result
FROM Testcases
  LEFT JOIN Tests
    ON Testcases.ID = Tests.TestCaseID
WHERE Tests.Release = "1.1.111"
   OR Tests.TestCaseID IS NULL

在表Testcases中再插入一行,ID=4, Testcase=20

并在表Tests 中输入一行,用TestCaseID=4 Result="Whatever" Release="2.2.37" 来查看这两个选项之间的区别。

简而言之,第一个查询将显示所有测试用例,结果仅显示具有Release="1.1.111" 的测试,其余测试用例将显示结果为空(NULL)。

第二个将只显示带有Release="1.1.111" 的测试用例。还有所有没有任何测试的Testcase。

注意:第一个查询不能在 Access 的“设计”模式下显示。您可以将其保存为 SQL 模式,但如果您关闭并重新打开它,Access 会出于未知原因删除一些括号。你仍然可以运行它。

它(第一个查询)也可以写成:

SELECT Testcases.Testcase
     , g.Result
FROM Testcases
 LEFT JOIN
   ( SELECT * 
     FROM Tests
     WHERE ( Tests.Release = "1.1.111" )
   )
   AS g
 ON ( Testcases.ID = g.TestCaseID )

SELECT Testcases.TestCase
     , Tests.Result
FROM Testcases
  INNER JOIN Tests
    ON ( Testcases.ID = Tests.TestCaseID )
WHERE ( Tests.Release = "1.1.111" ) 

UNION ALL 

SELECT Testcases.TestCase, NULL
FROM Testcases 
WHERE NOT EXISTS 
  ( SELECT 1
    FROM Tests
    WHERE ( Testcases.ID = Tests.TestCaseID )
      AND ( Tests.Release = "1.1.111" )
  )

甚至更好(因为它可以在设计模式下显示):

SELECT Testcases.Testcase
     , IIf((Tests.Release="1.1.111"), Tests.Result, Null)
       AS Result
FROM Testcases
  LEFT JOIN Tests
    ON Testcases.ID = Tests.TestCaseID
GROUP BY Testcases.Testcase
       , IIf((Tests.Release="1.1.111"), Tests.Result, Null)

【讨论】:

第一个给我“Tests.Release=.. 部分不支持加入表达式。第二个有效,但很想知道区别并确保这涵盖了我想要的。 用你指出的情况和第二种方式,我仍然没有从测试用例中获得完整的行集。 @Michael:编辑了第一个查询,它需要一对括号。【参考方案2】:

将过滤器放入您的联接条件中,以便将其作为联接的一部分应用,而不是事后过滤。例如:

SELECT Testcases.Testcase, Tests.Result
FROM (Testcases LEFT JOIN Tests ON ((Testcases.ID=Tests.TestCaseID)
 AND (Tests.Release="1.1.111")))

【讨论】:

当您在 where 子句中放置条件时,它会在您的左连接表上进行内部连接,因此正如 @steve 所说,您需要移动条件 MS Access 不接受这个...也尝试了大括号,结果相同:( 如何“移动”条件球员? 我已经修改了答案(带括号) - 你可以再试一次吗? 这种对大括号和方括号的挑剔是考虑使用 Access GUI 设计复杂查询的原因。

以上是关于LEFT JOIN 不返回 MS Access 左表中的所有行?的主要内容,如果未能解决你的问题,请参考以下文章

MS Access INNER JOIN/LEFT JOIN 问题

MS Access 多 (INNER, LEFT & RIGHT) JOIN 查询

MS Access - SQL LEFT JOIN 多个条件

MS-Access 2016 中的“同一张表”LEFT JOIN ON“同一个公共字段”

SQL语句中LEFT JOIN和RIGHT JOIN 以及INNER JOIN的区别

MS Access:左连接不返回左表中的所有行