【问题标题】: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;
  • 哦,我会试试的。谢谢
  • 您应该报告您拥有的输入数据的示例,以及您期望的查询结果。
  • 这可能是一个有趣的链接:stackoverflow.com/q/473607/2224701
  • 连接链从左到右进行评估。

标签: sql oracle join left-join inner-join


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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-04
        • 2018-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多