【问题标题】:LEFT JOIN in not returning full rows from left table in MS Access?LEFT JOIN 不返回 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";

【问题讨论】:

    标签: database ms-access ms-access-2007


    【解决方案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 设计复杂查询的原因。
    猜你喜欢
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多