左连接和内连接组

Posted

技术标签:

【中文标题】左连接和内连接组【英文标题】:left join and group of inner join 【发布时间】:2017-08-15 14:36:37 【问题描述】:

说,我有以下查询:

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 对应的条目,没关系,我还是想要它。

使用上面的伪代码,如果我按原样运行,显然不会达到同样的结果。

【问题讨论】:

也许你需要一个子查询:LEFT JOIN (SELECT some_col FROM table3 INNER JOIN table3_1 ON...INNER JOIN...) t3 ON t3.col_join = table1.col_join; 哦,我会试试的。谢谢 您应该报告您拥有的输入数据的示例,以及您期望的查询结果。 这可能是一个有趣的链接:***.com/q/473607/2224701 连接链从左到右进行评估。 【参考方案1】:

使用括号来强制连接顺序,有点

SELECT * 
FROM (
   TABLE1 
   JOIN TABLE2 ON ...)
LEFT JOIN (
    TABLE3 
    JOIN TABLE3_1 ON ...
    JOIN TABLE3_2 ON ...
    JOIN TABLE3_3 ON ...) ON ...

【讨论】:

【参考方案2】:

检查this answer。

@Serg 答案是正确的,但如果在语句末尾指定 ON 条件,则不需要使用括号。

SELECT * FROM TABLE1 
    JOIN TABLE2 ON ...
    LEFT JOIN TABLE3 ON ThisConditionShouldBeAtTheEnd
        JOIN TABLE3_1 ON ...
        JOIN TABLE3_2 ON ...
        JOIN TABLE3_3 ON ...

你这样重写:

SELECT * FROM TABLE1 
    JOIN TABLE2 ON ...
    LEFT JOIN TABLE3 
        JOIN TABLE3_1 ON ...
        JOIN TABLE3_2 ON ...
        JOIN TABLE3_3 ON ...
    ON ThisConditionShouldBeAtTheEnd

另见this article for more explanation。原因是 JOIN 条件是从左到右(自上而下)评估的,您需要在之前的内部连接之后评估 LEFT 连接条件。

【讨论】:

【参考方案3】:

免责声明:我手头没有可供检查的 Oracle 数据库,但希望它包含对您有所帮助的想法。

解决方案 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)

这种语法可能有效,但恕我直言,使用右连接会使语法难以理解。

【讨论】:

您的答案中缺少 TABLE3 吗?不确定正确的连接技巧是否适用于该示例,因为外部连接位于 2 个内部连接之间。 添加了 TABLE3。我认为右连接技巧应该起作用,因为最初的问题是左连接不在 2 个内连接之间,而是将内连接作为左参数,将直接单个表作为右侧参数,而不是完整的其他内连接。测试会给出答案;)【参考方案4】:

其他答案的替代方法是 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 ...

【讨论】:

以上是关于左连接和内连接组的主要内容,如果未能解决你的问题,请参考以下文章

如何使用左连接和内连接编写 laravel 查询?

结合左外连接和内连接 + 聚合函数 - 空结果集问题

ms-access 中的左连接和内连接

在同一个查询中使用左连接和内连接

sql左连接 右连接 内连接 外连接都是啥

SQL中内连接和外连接的区别