SQL 内连接到左连接表

Posted

技术标签:

【中文标题】SQL 内连接到左连接表【英文标题】:SQL inner joining to left joined table 【发布时间】:2015-02-18 17:38:51 【问题描述】:

所以这可能更像是一个关于 mysql 中的连接如何工作的理论问题,但我希望得到一些指导。

假设我有三个表,表 a、b 和 c,其中表 a 和 b 是事实表,表 c 是表 b 的维度表。如果我想将表 b 左连接到表 a(我想保留表 a 的所有内容,但也想匹配表 b 中的内容),即使表 b 左连接,我还能将表 c 内连接到表 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

【问题讨论】:

那个连接会杀死左连接。如果你把 b 放在一个 where is 也会杀死左边。 【参考方案1】:

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
;

在这种情况下,表 tablebtablec 首先连接,然后它们的连接结果外连接到 tablea

不过,最终结果集将与 @simon at rcl's solution 相同。

【讨论】:

【参考方案2】:

在这种情况下,如果 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

即使没有匹配的 tableb 行,也会得到每一个 tablea 行,当没有 tablec 行时,也会得到每个 tablea 和 tableb。

【讨论】:

【参考方案3】:

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

select *
from      t1
left join t2 on t2.t1_id = t1.id
join      t3 on t3.id    = t1.t3_id

完全一样

select *
from      t1
join      t3 on t3.id    = t1.t3_id
left join t2 on t2.t1_id = t1.id

这是select 查询工作原理的概念模型。当然,Once 应该注意到,由于第 1 步隐含的性能影响,除了最微不足道的 SQL 实现之外,没有什么会真正做到这一点。但是,结果就像您完成了以下步骤一样。

    构造from 子句中指定的所有表的笛卡尔积。这是您的候选结果集。 应用连接条件从候选结果集中消除行。

    应用where 子句中指定的条件来进一步缩小结果集。

    注意:第二步和第三步中的区别可能会改变结果集,具体取决于特定测试是放在where 子句还是join 标准中。这不是内部连接的问题,但是对于外部连接,测试的位置可以大大改变结果。不要问我是怎么知道的。

    应用group by 子句(如果有)中指定的条件将结果集划分为组。

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

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

    通过应用having 子句(如果有)中指定的条件进一步筛选结果集。

    此时,您已获得最终结果集。根据order by 子句中指定的标准对其进行排序。

【讨论】:

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

SQL中有几种连接?有啥区别?(左连右连内连和外连?)

mysql优化5表左连接

交叉表左连接,Django ORM

SQLServer 多表左连接

MYSQL 表左连接 ON AND 和ON WHERE 的区别

MySql表的内连和外连