"FROM a, b" 和 "FROM a FULL OUTER JOIN b" 有什么区别?(涉及IT技术)

5
当处理来自多个表的数据时,有多种不同的方法可以连接这些表格,每种方法都会改变匹配列的处理方式。您也可以只从多个表中提取数据,即FROM [table a], [table b]
这种方法似乎仍然以某种方式连接了这些表格,如果我猜的话,我会说这种方法只是FULL OUTER JOIN的简写,但我确定两种方法之间有所不同。
区别仅仅在于FULL OUTER JOIN后跟随ON [table 1 specific column] = [table 2 specific column],还是其他什么事情发生了?

这个问题已经被问过了,但是问题中有一些额外的变量让可能的答案变得混乱,而且答案本身虽然准确,但没有详细说明如何解决这种混乱。由于我无法在问题上进行评论以请求澄清,因此我提出了一个新问题。如果答案揭示了这个问题有额外的变量,那么这些变量将从这个问题中删除,以避免混淆未来的读者。原始问题:lin - Space Ostrich
2个回答

12
你的问题已经得到解答,但从你的评论中我了解到你是否完全理解这个问题还存在一定的不确定性。因此,我想再添加一个答案来帮助你 :-)
让我们从简单的开始。
FROM a, b

这是一种过时的连接语法,已被标准SQL-1992中的显式连接所取代。在上述语法中,如果有连接条件,必须将其放在WHERE子句中。如果在WHERE子句中没有连接条件,则为交叉连接,现在应该明确地写成

FROM a CROSS JOIN b

这说明你有意想要得到所有a和b的组合(而不仅仅是忘记了连接条件或错误地删除了它)。一个例子是:
FROM store CROSS JOIN product

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

store   product
s1      p1
s1      p2
s2      p1
s2      p2

CROSS JOIN 很少需要使用。在上述情况下,我们可能希望知道所有商店的产品/组合,并为每行选择一个'yes'或'no',以便我们看到商店有哪些产品,哪些没有。

在关系型数据库中,通常涉及表之间的关系,因此让我们添加连接条件:

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

假设表格包含:

年份   部门编号   总成本
2015   d001      20000
2016   d001      25000
2016   d002      10000

年份   部门编号   总利润
2015   d001      40000
2015   d002      30000
2016   d001      50000

那么结果将是:

年份   部门编号   总成本   总利润
2015   d001      20000    40000
2016   d001      25000    50000

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

如果你想要看到其他数据,你必须使用外连接。您可以将dept_gain与dept_cost进行外连接,以查看所有成本 - 以及它们的收益(如果有)。反之亦然,您可以将dept_cost与dept_gain进行外连接,以查看所有收益 - 以及它们的成本(如果有)。或者,您可以使用完全外连接,以查看所有数据

FROM dept_cost
FULL OUTER JOIN dept_gain ON dept_gain.dept_no = dept_cost.dept_no 
                          AND dept_gain.year = dept.cost.year
年份    部门编号    总花费    总收益
2015   d001      20000     40000
2015   d002               30000
2016   d001      25000     50000
2016   d002      10000        

交叉连接(CROSS JOIN)和全外连接(FULL OUTER JOIN)很少使用,所以如果您还不理解它们,不要担心。通常只需要内连接(INNER JOIN),有时需要左外连接(LEFT OUTER JOIN)。


随着这个想法的闪现,一切都变得清晰了。写得非常好,如果我遇到问题,肯定会将其保留在浏览器标签页中。 - Space Ostrich

3
在第一种情况下,您应用了一个CROSS JOIN(或笛卡尔积)-如果您不使用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 的简写吗? - Space Ostrich
@SpaceOstrich:不是的,第一个版本是CROSS连接,而不是内连接。 - user330315
@SpaceOstrich:我已经添加了完整信息,包括关于INNER JOIN的情况(与问题无关)。 - Joe Taras
我认为交叉连接是一种内连接,没有连接条件。(所有行都组合在一起,没有关系,也没有“索引号”。) - jarlh
我认为我已经基本掌握了它,但希望我能在注释中使用换行符,这样我就可以格式化表格了,但没关系。我还有点困惑,但考虑到我最多只做了6个小时的SQL,我想很快就会"恍然大悟"的。我将其标记为已解决,也许将来我会重新格式化我的问题,以便新程序员更容易使用。解释语法等等。 - Space Ostrich
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接