说,我有以下查询:
SELECT * FROM TABLE1
JOIN TABLE2 ON ...
LEFT JOIN TABLE3 ON ...
JOIN TABLE3_1 ON ...
JOIN TABLE3_2 ON ...
JOIN TABLE3_3 ON ...
我想要实现的是TABLE3,TABLE3_1,TABLE3_2,TABLE3_3内部连接(我只需要它们之间的所有匹配数据,其余的都没有)。然后对于TABLE1,TABLE2也有内部连接。但是从TABLE1 + TABLE2结果来看,有些人没有相应的TABLE3条目,没关系,我仍然会想要它。
如果按原样运行上面的伪代码,显然它不会达到相同的结果。
答案 0 :(得分:8)
使用paretheses强制加入顺序,
SELECT *
FROM (
TABLE1
JOIN TABLE2 ON ...)
LEFT JOIN (
TABLE3
JOIN TABLE3_1 ON ...
JOIN TABLE3_2 ON ...
JOIN TABLE3_3 ON ...) ON ...
答案 1 :(得分:2)
检查this answer。
@Serg答案是正确的,但如果在语句末尾指定posts
条件,则不需要使用括号。
ON
你这样改写:
SELECT * FROM TABLE1
JOIN TABLE2 ON ...
LEFT JOIN TABLE3 ON ThisConditionShouldBeAtTheEnd
JOIN TABLE3_1 ON ...
JOIN TABLE3_2 ON ...
JOIN TABLE3_3 ON ...
另见this article for more explanation。原因是JOIN条件从左到右(自上而下)进行评估,并且您需要在之前的内部连接之后评估LEFT连接条件。
答案 2 :(得分:1)
免责声明:我手头没有oracle DB可以检查,但希望它会包含一些帮助你的想法。
解决方案1:您可以使用括号来表示(TABLE3 x N)的中间连接表。伪代码:
select *
FROM TABLE1
inner join TABLE2 on (condition)
left join (
table3
inner join table3_1 on (condition)
inner join table3_2 on (condition)
inner join table3_3 on (condition)
) as table3_joined ON (table3_joined.ID = table2.id)
至少可以在MSSQL上运行。我无法验证它在oracle中是否有效,但您可以尝试。我认为这种语法非常明确,易于遵循/维护。
解决方案2:另一种方法是重复使用相同的从左到右的顺序,这种顺序会让您使用正确的连接来帮助您。伪代码:
select *
from table3
inner join table3_1 on (condition)
inner join table3_2 on (condition)
inner join table3_3 on (condition)
right join table2 on (condition)
inner join table1 on (condition)
这种语法可能有效,但imho使用正确的连接会使语法更难以理解。
答案 3 :(得分:0)
其他答案的替代方案是CTE(公用表表达式)。这只是对内连接table3组的查询以及对内连接table1 / table 2组的查询,并且这两个组在主查询中是外连接的。对我来说(显然这是主观的)如果我在其他人的代码中遇到它,我会发现这更容易理解发生了什么。
WITH
t3_group AS
(SELECT *
FROM table3 ON ...
INNER JOIN table3_1 ON ...
INNER JOIN table3_2 ON ...
INNER JOIN table3_3 ON ... ),
t1_t2_group AS
(SELECT *
FROM table1
INNER JOIN table2 ON ...)
SELECT *
FROM t1_t2_group
LEFT JOIN t3_group ON ...