好的,我会尝试简化我遇到的问题。
我有4张桌子:
表A:
OneID
表B:
OneID (FK to TableA)
TwoID (FK to TableC)
表C:
TwoID
ThreeID (FK to TableD)
提出:
ThreeID
我需要一个查询来检索所有这四个表中的数据。
查询条件是:
答案 0 :(得分:1)
我并非100%确定我理解正确,但无论如何我都会尽力帮助。您似乎需要在表D上执行FULL OUTER JOIN
:
SELECT
*
FROM
TableA AS A INNER JOIN
TableB AS B ON B.A_Id = A.Id INNER JOIN
TableC AS C ON C.B_Id = B.Id FULL OUTER JOIN
TableD AS D ON D.C_Id = C.Id
如果我误解了您的要求并且您需要更复杂的标准,您可以在所有表格上FULL OUTER JOIN
并在WHERE
部分中添加额外条件:
SELECT
*
FROM
TableA AS A FULL OUTER JOIN
TableB AS B ON B.A_Id = A.Id FULL OUTER JOIN
TableC AS C ON C.B_Id = B.Id FULL OUTER JOIN
TableD AS D ON D.C_Id = C.Id
WHERE
--if a record is in Table D but not in Table C, then it must always be present in the results
(D.Id IS NOT NULL AND C.Id IS NULL) OR
(
--otherwise if a record is in Table D and Table C, then it should only be present if it is in the result of the A,B,C join
(D.Id IS NOT NULL AND C.Id IS NOT NULL) AND
--want to inner join tables A, B, C
(A.Id IS NOT NULL AND B.Id IS NOT NULL AND B.Id IS NOT NULL)
)
答案 1 :(得分:1)
您所描述的场景实际上并不可能(或者至少它们不合逻辑)
如果记录在表D中但在表C中没有,那么它必须始终存在于结果
中
记录可以“在表D中而不在表C中”的唯一方法是,如果表D中的外键为空,没有从表D到表A或B的链接,则没有其他方法可以定义记录存在于D而不是C:
否则,如果记录在表D和表C中,那么只有当它在A,B,C连接的结果中时才存在
同样,这可能发生的唯一方法是使用NULLABLE外键。无论我认为以下任何一项都能为您提供所需的结果:
SELECT A.OneID, B.TwoID, c.ThreeID, D.FourID
FROM D
LEFT JOIN (C
INNER JOIN B
ON B.TwoID = C.TwoID
INNER JOIN A
ON A.OneID = B.OneID)
ON C.ThreeID = D.ThreeID;
或者
SELECT A.OneID, B.TwoID, c.ThreeID, D.FourID
FROM A
INNER JOIN B
ON B.OneID = A.OneID
INNER JOIN C
ON C.TwoID = B.TwoID
RIGHT JOIN D
ON D.ThreeID = C.ThreeID
或者
SELECT A.OneID, B.TwoID, c.ThreeID, D.FourID
FROM A
INNER JOIN B
ON B.OneID = A.OneID
INNER JOIN C
ON C.TwoID = B.TwoID
INNER JOIN D
ON D.ThreeID = C.ThreeID
UNION ALL
SELECT NULL, NULL, NULL, FourID
FROM D
WHERE ThreeID IS NULL;
<强> Examples on SQL Fiddle 强>
前两个具有相同的执行计划,这只是一个偏好问题,我个人不喜欢使用RIGHT JOIN
因为它使查询感觉它们的顺序错误,即从下到上,但这纯粹是我的偏爱。最后一个查询可能会更好,具体取决于您的数据的基数和您拥有的任何索引
修改强>
根据您修改后的标准,我认为最简单的方法是使用UNION ALL:
SELECT A.OneID, B.TwoID, c.ThreeID, d3 = D.ThreeID
FROM A
INNER JOIN B
ON B.OneID = A.OneID
INNER JOIN C
ON C.TwoID = B.TwoID
INNER JOIN D
ON D.ThreeID = C.ThreeID
UNION ALL
SELECT NULL, NULL, NULL, ThreeID
FROM D
WHERE NOT EXISTS (SELECT 1 FROM C WHERE C.ThreeID = D.ThreeID);
<强> Example on SQL Fiddle 强>