【问题标题】:In SQL, a Join is actually an Intersection? And it is also a linkage or a "Sideway Union"?在 SQL 中,Join 实际上是一个 Intersection?而且也是联动还是“侧向联盟”?
【发布时间】: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 视为“交叉点”吗?但是它的“链接”或“横向联合”方面呢?

【问题讨论】:

    标签: sql mysql join union intersection


    【解决方案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,但它们并不相同,应根据情况选择。

        【讨论】:

          猜你喜欢
          • 2012-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多