【问题标题】:What is the difference between "FROM a, b" and "FROM a FULL OUTER JOIN b"?“FROM a, b”和“FROM a FULL OUTER JOIN b”有什么区别?
【发布时间】:2016-08-28 02:09:24
【问题描述】:

处理来自多个表的数据时,您可以通过多种不同的方式JOIN 这些表,每种方式都会改变处理匹配列的方式。您也可以从多个表中提取数据,即FROM [table a], [table b]

这种方法似乎仍然以某种方式加入表格,如果我不得不猜测我会说这种方法只是FULL OUTER JOIN 的简写,但我确信两者之间存在差异。

区别仅仅是FULL OUTER JOIN后面跟着ON [table 1 specific column] = [table 2 specific column],还是有别的原因?

【问题讨论】:

  • 这个问题已经被问过了,但是,这个问题被问到了额外的变量,混淆了可能的答案,而答案本身虽然准确,但没有足够详细地解决这种混淆。由于我无法对要求澄清的问题发表评论,因此我要问一个新问题。如果答案显示这个问题有额外的变量,这些变量将从这个问题中删除,以避免混淆未来的读者。原问题:lin

标签: sql join full-outer-join


【解决方案1】:

您的问题已得到解答,但从您的客户那里我了解到您是否完全理解了问题仍然没有安全感。所以,我想我只是添加另一个答案:-)

让我们从简单的开始

FROM a, b

这是一种过时的连接语法,在标准 SQL-1992 中已被显式连接所取代。使用上述方法,您必须将连接条件(如果有)放在 WHERE 子句中。如果 WHERE 子句中没有连接条件,这是一个交叉连接,您现在可以明确写为

FROM a CROSS JOIN b

这告诉读者您有意地想要 a 和 b 的所有组合(并且不仅忘记了连接条件或错误地删除了它)。一个例子是

FROM store CROSS JOIN product

在这里,您将每个商店与每种产品结合起来,无论商店是否真的有产品;您只需显示所有可能的组合。如果有两家商店和两种产品,结果可能如下所示:

商店产品 s1 p1 s1 p2 s2 p1 s2 p2

很少需要交叉连接。在上述情况下,我们可能想知道所有商店的产品/组合,并为每一行选择“是”或“否”,这样我们就可以看到哪些产品是商店的特色,哪些不是。

然而,在关系数据库中,我们通常处理表的关系,所以让我们添加连接条件:

FROM a, b
WHERE a.col1 = b.col2

这是一个内部连接,我们只寻找记录匹配。现在写成

FROM a
INNER JOIN b ON a.col1 = b.col2

或(省略可选关键字INNER,因为默认情况下连接是内连接):

FROM a
JOIN b ON a.col1 = b.col2

这是一个例子。我们有两个表格,分别包含每个部门和年度的费用和收入。

FROM dept_cost
JOIN dept_gain ON dept_gain.dept_no = dept_cost.dept_no AND dept_gain.year = dept.cost.year

假设表格包含:

年份 dept_no total_cost 2015 d001 20000 2016 d001 25000 2016 d002 10000

年份 dept_no total_gain 2015 d001 40000 2015 d002 30000 2016 d001 50000

那么结果是:

年份 dept_no total_cost total_gain 2015 d001 20000 40000 2016 d001 25000 50000

因为在两个表中只能找到 2015/d001 和 d001/2016。

如果您也想查看其他数据,则必须外连接。您可以将 dept_gain 外部连接到 dept_cost,以便查看所有成本 - 以及它们的收益(如果有)。或者,反之亦然,您将 dept_cost 外连接到 dept_gain,以便查看 所有 收益 - 以及它们的成本(如果有)。或者你full outer join,以便查看所有数据

FROM dept_cost
FULL OUTER JOIN dept_gain ON dept_gain.dept_no = dept_cost.dept_no 
                          AND dept_gain.year = dept.cost.year
年份 dept_no total_cost total_gain 2015 d001 20000 40000 2015 d002 30000 2016 d001 25000 50000 2016 d002 10000

很少需要 CROSS JOIN 和 FULL OUTER JOIN。因此,如果您还不了解它们,请不要担心。您通常只需要 INNER JOIN,有时只需要 LEFT OUTER JOIN。

【讨论】:

  • 就这样,它点击了。写得很好,如果我遇到问题,肯定会在标签中保持打开状态。
【解决方案2】:

在第一种情况下,您应用 CROSS JOIN(或 Cartersian 产品) - 如果您不使用 WHERE 子句来链接您的字段(在这种情况下,您有一个 INNER JOIN),在第二种情况下您应用FULL OUTER JOIN

区别

使用笛卡尔积,您可以将第一个表的每一行与第二个表的每一行链接起来

使用FULL OUTER JOIN,您可以将第一个表的行与第二个表的行链接起来,但如果不满足关系,则两侧的其中一个为 NULL。

示例

假设你有两个这样的表:

CREATE TABLE a (id_a int)
CREATE TABLE b (id_b int)

包含以下内容:

INSERT INTO A (1)
INSERT INTO A (2)

INSERT INTO B (2)
INSERT INTO B (3)

在第一种情况下,(笛卡尔积)您将拥有:

SELECT * FROM A, B

1 2
1 3
2 2
2 3

在第二种情况下,您将拥有:

SELECT * FROM A FULL OUTER JOIN B
ON A.ID_A = B.ID_B

1    NULL
2    2
NULL 3

如果你写:

SELECT * FROM A,B WHERE A.ID_A = B.ID_B 

与此相同:

SELECT * FROM A JOIN B ON A.ID_A = B.ID_B

有了这个结果:

2 2

【讨论】:

  • 那会使第一个方法成为INNER JOIN 的简写吗?
  • @SpaceOstrich:不。第一个版本是 CROSS 连接,而不是内部连接
  • @SpaceOstrich:我添加了完整的信息,关于 INNER JOIN 的案例(不涉及问题)
  • 所以如果我理解这一点,在CROSS JOIN 中,这两个表只是由“索引号”匹配。而不是拥有一个用于合并数据的共享列?
  • 我认为交叉连接是内部连接,没有连接条件。 (所有行合并,没有关系,没有“索引号”。)
猜你喜欢
  • 2012-10-25
  • 2018-06-27
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
相关资源
最近更新 更多