在 SQL 中,Join 实际上是一个 Intersection?而且也是联动还是“侧向联盟”?

Posted

技术标签:

【中文标题】在 SQL 中,Join 实际上是一个 Intersection?而且也是联动还是“侧向联盟”?【英文标题】:In SQL, a Join is actually an Intersection? And it is also a linkage or a "Sideway Union"? 【发布时间】:2011-02-11 23:01:08 【问题描述】:

我一直认为 SQL 中的 Join 是两个表之间的某种链接。

例如,

select e.name, d.name from employees e, departments d 
  where employees.deptID = departments.deptID

在这种情况下,它链接两个表,以显示每个员工的部门名称而不是部门 ID。有点像“联动”或“联合”。

但是,在了解了inner join vs outer join之后,发现Join(Inner join)其实是一个交集。

例如,当一个表的 ID 为 1、2、7、8,而另一个表的 ID 为 7 和 8 时,我们得到交集的方式是:

select * from t1, t2 where t1.ID = t2.ID

得到“7和8”的两条记录。所以它实际上是一个十字路口。

所以我们有 2 个表的“交集”。将此与 2 个表上的“联合”操作进行比较。可以将 Join 视为“交叉点”吗?但是它的“链接”或“横向联合”方面呢?

【问题讨论】:

【参考方案1】:

你在正确的轨道上; INNER JOIN 返回的行是满足连接条件的行。但这就像一个交集,只是因为您在连接条件中使用了 equality,应用于每个表中的列。

还要注意,INTERSECTION 已经是一个 SQL 操作,它还有另一个含义——它与 JOIN 不同。

SQL JOIN 可以生成一种新类型的行,其中包含两个连接表中的所有列。例如:col4、col5、col6 不存在于表 A 中,但它们存在于与表 B 的连接结果中:

SELECT a.col1, a.col2, a.col3, b.col4, b.col5, b.col6
FROM A INNER JOIN B ON a.col2=b.col5;

SQL INTERSECTION 返回两个单独表共有的行,这两个表必须已经有 相同的 列。

SELECT col1, col2, col3 FROM A
INTERSECT
SELECT col1, col2, col3 FROM B;

这恰好产生与以下连接相同的结果:

SELECT a.col1, a.col2, a.col3
FROM A INNER JOIN B ON a.col1=b.col1 AND a.col2=b.col2 AND a.col3=b.col3;

并非每个品牌的数据库都支持INTERSECTION 运算符。

【讨论】:

【参考方案2】:

连接 'links' 或 erm... 连接两个表中的行。我认为这就是您所说的“横向联合”的意思,尽管我个人认为这是一种糟糕的表达方式。但是有不同类型的连接做的事情略有不同:

内连接确实是一个交集。 完全外连接是联合。

Jeff Atwood 博客上的 page 描述了其他可能性。

【讨论】:

说,如果两个表都有匹配的deptID,那么两个表并排合并,从这个意义上说它就像一个“横向联合” @Jian Lin:如果它让您更容易将其视为“横向联合”,那很好,但联合在 SQL 中具有明确定义的含义,但事实并非如此。在与其他人交谈时,我会避免使用该术语。【参考方案3】:

外连接 - 与联合或联合所有无关。

例如,“null”不会作为 Union 或 Union All 操作的结果出现,而是由 Outer Join 产生。

【讨论】:

【参考方案4】:

INNER JOIN 将两个 NULLs 视为两个不同的值。因此,如果您基于一个可为空的列进行连接,并且如果两个表在该列中都有 NULL 值,那么 INNER JOIN 将忽略这些行。

因此,要正确检索两个表之间的所有公共行,应使用INTERSECTINTERSECT 将两个 NULLs 视为相同的值。

示例(SQLite):

创建两个可空列的表:

CREATE TABLE Table1 (id INT, firstName TEXT);
CREATE TABLE Table2 (id INT, firstName TEXT);

插入NULL 值:

INSERT INTO Table1 VALUES (1, NULL);
INSERT INTO Table2 VALUES (1, NULL);

使用INNER JOIN 检索公共行(这显示没有输出):

SELECT * FROM Table1 INNER JOIN Table2 ON 
    Table1.id=Table2.id AND Table1.firstName=Table2.firstName;

使用INTERSECT 检索公共行(这正确显示了公共行):

SELECT * FROM Table1 INTERSECT SELECT * FROM Table2;

结论:

尽管很多时候INTERSECTINNER JOIN 都可用于获取same results,但它们并不相同,应根据情况选择。

【讨论】:

以上是关于在 SQL 中,Join 实际上是一个 Intersection?而且也是联动还是“侧向联盟”?的主要内容,如果未能解决你的问题,请参考以下文章

CROSS JOIN

通过 LEFT JOIN 优化 SQL 子查询

ORDER BY date SQL with LEFT JOIN 用于消息传递

SQL学习多表关联-join

从 SQL Join 中删除重复项

求助sql语句,多个join嵌套