SQL内连接到左连接表

ben*_*890 5 mysql sql left-join

所以这可能更多是关于MySQL如何工作的理论问题,但我喜欢一些指导.

假设我有三个表,表a,b和c,其中表a和b是事实表,表c是表b的维表.如果我想要将表b连接到表a(我想保留表a的所有内容,但也想要表b中的匹配内容),我是否仍然可以将表c连接到表b,即使表b仍然连接?或者我是否必须将表c连接到表b?或者这两种意图和目的是否会产生相同的结果?

select a.column, c.name
from tablea a
left join tableb b on a.id = b.id
inner join (?) tablec c on b.name_id = c.name
Run Code Online (Sandbox Code Playgroud)

And*_*y M 18

MySQL支持允许您实现所需内容的语法:

select a.column, c.name
from
  tablea a
  left join
    tableb b
    inner join tablec c on b.name_id = c.name
   on a.id = b.id
;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,表tablebtablec第一个连接,然后它们的连接结果是外连接到tablea.

然而,最终结果集与rcl解决方案中的@simon相同.


sim*_*rcl 6

在这种情况下,如果 tableb 没有 tablec 条目,则整个连接将失败,并且 tablea 行将不会被包含在内。要包含 tablsa 条目,您需要将与 tablc 的连接设为左连接:

select a.column, c.name
from tablea a
left join tableb b on a.id = b.id
left join tablec c on b.name_id = c.name
Run Code Online (Sandbox Code Playgroud)

即使没有匹配的 tableb 行,这也会获得每个 tablea 行,并且当没有 tablec 行时也会获得每个 tablea 和 tableb。


Nic*_*rey 5

就 SQL 而言,连接顺序无关紧要(连接条件隐含的任何顺序除外)。就像是

select *
from      t1
left join t2 on t2.t1_id = t1.id
join      t3 on t3.id    = t1.t3_id
Run Code Online (Sandbox Code Playgroud)

完全一样

select *
from      t1
join      t3 on t3.id    = t1.t3_id
left join t2 on t2.t1_id = t1.id
Run Code Online (Sandbox Code Playgroud)

这是查询如何工作的概念模型select。当然,应该注意的是,由于步骤 #1 隐含的性能影响,除了最简单的 SQL 实现之外,没有任何其他方法实际上会执行此操作。但是,结果将与您执行以下步骤一样。

  1. 构造子句中指定的所有表的笛卡尔积from。这是您的候选结果集。
  2. 应用连接条件从候选结果集中消除行。
  3. 应用子句中指定的条件where进一步缩小结果集范围。

    注意:第二步和第三步中的区别可能会更改结果集,具体取决于特定测试是否放置在子句wherejoin条件中。这不是内部联接的问题,但对于外部联接,测试的位置可能会严重改变结果。别问我怎么知道这些。

  4. 应用子句中指定的条件group by(如果有)将结果集分区。

  5. 对于每个组,计算指定的任何聚合函数的值。

  6. 将每个组折叠成一行,由其键值(来自子句group by)及其聚合函数的值组成。

  7. 通过应用子句中指定的标准(如果有)进一步筛选结果集having

  8. 此时,您已获得最终结果集。根据order by条款中指定的标准进行订购。