FULL OUTER JOIN 不返回所有表的内容

Posted

技术标签:

【中文标题】FULL OUTER JOIN 不返回所有表的内容【英文标题】:FULL OUTER JOIN is not returning content of all tables 【发布时间】:2021-06-09 20:26:34 【问题描述】:

如下所述,我有 3 张桌子。

表格

BUG

Id | Name | Other information ...
1  | Bug1 | ...
2  | Bug2 | ...
3  | Bug3 | ...
4  | Bug4 | ...
5  | Bug5 | ...

链接

Id  | Test_id | Bug_id
100 | 1000    | 4
101 | 1100    | 2
102 | 1200    | 2
103 | 1200    | 5

测试

Id   | Name | Other information ...
1000 | TC1  | ...
1100 | TC2  | ...
1200 | TC3  | ...
1300 | TC4  | ...
1400 | TC5  | ...
1500 | TC6  | ...

请求

SELECT Bug.Id, Bug.Name, Test.Id, Test.Name
FROM Test FULL OUTER JOIN Link ON Link.Test_id = Test.Id
FULL OUTER JOIN Bug ON Link.Bug_id = Bug.Id
INNER JOIN Test_Detail ON Test_Detail.Test_id = Test.Id
INNER JOIN Release ON Release.Id = Test.Release_id
INNER JOIN Cycle ON Cycle.Release_id = Release.Id

但是,这并没有提供预期的结果......

预期结果

如果有链接,我想获取有关该错误的信息和 测试 如果有没有链接的错误,我想得到 错误信息 如果有没有链接的测试,我想获取有关测试的信息

结果

BugId | BugName | TestId | TestName
1     | Bug1    |
2     | Bug2    | 1100   | TC2
2     | Bug2    | 1200   | TC3
3     | Bug3    |
4     | Bug4    | 1000   | TC1
5     | Bug5    | 1200   | TC2
      |         | 1300   | TC4
      |         | 1400   | TC5
      |         | 1500   | TC6
    

结论

FULL OUTER JOIN 不是要使用的正确连接吗?您能否帮助了解为什么它没有按预期工作?

谢谢

编辑 1

结果基于 Charlieface 的回答。

我得到了错误、测试和链接。但如果它存在,我只需要链接。如果没有链接,我需要测试和错误详细信息。如上文预期结果部分所述。

BugId | BugName | TestId | TestName
      |         | 1100   | TC2
      |         | 1200   | TC3
2     | Bug2    |        | 
2     | Bug2    | 1100   | TC2
2     | Bug2    | 1200   | TC3

编辑 2

完整请求

TESTCYCL 在这篇文章中是TEST

SELECT DISTINCT
B.BG_BUG_ID
, B.BG_STATUS
, B.BG_SUMMARY
, B.BG_USER_TEMPLATE_13
, B.BG_SEVERITY
, B.BG_PRIORITY
, B.BG_USER_TEMPLATE_10
, B.BG_USER_TEMPLATE_08
, R.REL_NAME
, RC2.RCYC_NAME
, B.BG_DETECTION_DATE
, B.BG_RESPONSIBLE
, B.BG_USER_TEMPLATE_03
, B.BG_USER_03
, B.BG_CLOSING_DATE
, B.BG_USER_TEMPLATE_19
, B.BG_USER_TEMPLATE_18
, B.BG_DETECTED_BY
, TC.TC_TESTCYCL_ID
, TC.TC_TEST_ID
, T.TS_NAME
, TC.TC_STATUS
, T.TS_USER_TEMPLATE_05
, CF.CF_ITEM_NAME
, C.CY_CYCLE
, RC1.RCYC_NAME
, TC.TC_USER_TEMPLATE_06
, TC.TC_USER_TEMPLATE_05
, TC.TC_USER_TEMPLATE_08
FROM TESTCYCL AS TC
INNER JOIN RELEASE_CYCLES AS RC1 ON TC.TC_ASSIGN_RCYC = RC1.RCYC_ID
INNER JOIN TEST AS T ON TC.TC_TEST_ID = T.TS_TEST_ID
INNER JOIN CYCLE AS C ON TC.TC_CYCLE_ID = C.CY_CYCLE_ID
INNER JOIN CYCL_FOLD AS CF ON C.CY_FOLDER_ID = CF.CF_ITEM_ID
FULL OUTER JOIN LINK AS L ON L.LN_ENTITY_ID = TC.TC_TESTCYCL_ID
FULL OUTER JOIN BUG AS B
INNER JOIN RELEASE_CYCLES AS RC2 ON B.BG_DETECTED_IN_RCYC = RC2.RCYC_ID
INNER JOIN RELEASES AS R ON B.BG_DETECTED_IN_REL = R.REL_ID
ON L.LN_BUG_ID = B.BG_BUG_ID

【问题讨论】:

什么是内连接,可能会影响它。 @DaleK 呵呵,full join 什么时候做的? 我有 4 个内部连接来从其他表中获取内容,但只链接到 testbug。它应该不会影响testbuglink之间的链接。 这就是的想法。请edit 并添加完整查询 我在请求中添加了INNER JOIN。它仅用于获取有关测试的更多信息。 FULL JOIN ON 返回 INNER JOIN ON 行 UNION ALL 不匹配的由 NULL 扩展的左右表行。作为 OUTER JOIN ON 的一部分,始终知道您想要什么 INNER JOIN ON。在 FULL JOIN ON 之后,需要 right/left/2 [sic] 表的某些列不为 NULL 的 WHERE、HAVING 或 INNER JOIN 删除此类表的列的 NULL 扩展行,即只留下 RIGHT/LEFT/INNER [sic] JOIN ON 行,即“将 FULL JOIN 变为 RIGHT/LEFT/INNER JOIN”。你有那个。 【参考方案1】:

您需要重新排序您的联接。

将与一个表相关的所有inner joins 与该表放在一起。:

SELECT Bug.Id, Bug.Name, Test.Id, Test.Name
FROM Test
INNER JOIN Test_Detail ON Test_Detail.Test_id = Test.Id
INNER JOIN Release ON Release.Id = Test.Release_id
INNER JOIN Cycle ON Cycle.Release_id = Release.Id
FULL OUTER JOIN Link ON Link.Test_id = Test.Id
FULL OUTER JOIN Bug ON Link.Bug_id = Bug.Id

让我们假设你也想在Bug 上加入一些东西。为此,您需要嵌套ON 条件:

SELECT Bug.Id, Bug.Name, Test.Id, Test.Name
FROM Test
INNER JOIN Test_Detail ON Test_Detail.Test_id = Test.Id
INNER JOIN Release ON Release.Id = Test.Release_id
INNER JOIN Cycle ON Cycle.Release_id = Release.Id
FULL OUTER JOIN Link ON Link.Test_id = Test.Id
FULL OUTER JOIN Bug
      INNER JOIN Bug_Detail bd ON bd.Bug_id = Bug.id
  ON Link.Bug_id = Bug.Id

请注意,与流行观点相反,括号() 在这里没有什么区别,尽管它们在视觉上很有用。 ON 子句的顺序很重要:Bug_detail 内连接嵌套在 Bug 的全连接内

【讨论】:

感谢您提供这个非常有趣的答案!但是,如果有链接,request 返回一行错误,一行错误和链接的测试,一行测试。我在帖子中举了一个例子。如果有链接,我就不用拿bug和测试记录了。 我从您的原始编辑中复制了一个错误类型,现在已修复。您是否在使用 任何其他 joinwhere 谓词,因为这应该有效? 我没有使用 where 子句,并且对于您解释了如何为测试和错误执行的连接。然而奇怪的是,对于某些错误,我有一行包含错误详细信息,另一行包含错误和测试详细信息。相同的错误但出现了 2 次(一次没有关联测试,一次有关联测试) 这是不可能的,除非您有其他谓词或连接,或者 bugid 不匹配(可能是尾随空格或其他东西)。从您给出的结果来看,您确实有一个额外的谓词somewhere(可能在查询的其他地方)。请edit 并添加您当前的查询完整 我添加了完整的查询。我看不出你的回答有什么不同(当然是 SELECT)【参考方案2】:

您的内部连接正在将完整的外部连接变成其他东西。重新排列连接并使用括号:

SELECT Bug.Id, Bug.Name, Test.Id, Test.Name
FROM (Test JOIN
      Test_Detail
      ON Test_Detail.Test_id = Test.Id JOIN
      Release
      ON Release.Id = Test.Release_id JOIN
      Cycle
      ON Cycle.Release_id = Release.Id
     ) FULL OUTER JOIN
     Link
     ON Link.Test_id = Test.Id FULL OUTER JOIN
     Bug
     ON Link.Bug_id = Bug.Id;

【讨论】:

括号什么都不做,这是ON子句的顺序 @philipxy 。 . .因为该逻辑可以在FROM 子句中的任何位置。如果它遵循其他表引用,则需要括号(这是我编写查询的原始方式)。谢谢你的慰问。了解FULL JOIN 是应用于它之前的all 内部连接还是仅应用于最近的表也很棘手。结果完全不同,我更喜欢在这些情况下使用括号来非常清楚地表达意图。 我不明白“该逻辑可能在 FROM 子句中的任何位置”。我想您的意思是我所期望的,您使用括号表示最好将封闭的表视为一个单元,以最清晰的查询含义结构,因为人们可能会使用 CTE 和/或可能会使用指示评论所描述的值。但很多时候我们可以做到但我们做不到。 无论如何,我认为问题帖的规范不连贯,整个演示文稿一团糟。 我不明白您的“FULL JOIN 是否适用于所有内部连接”,因为连接总是将所有内容作为左参数。尽管交叉和内连接是可交换的,所以我们可以重新排列它们链中参数的顺序。 (只要 ON 中的列保持在范围内。但是我们有类似的选项来重新排列 ON 连词的位置。)

以上是关于FULL OUTER JOIN 不返回所有表的内容的主要内容,如果未能解决你的问题,请参考以下文章