Full outer Join 导致行数多于任一父数据集的原因是什么?

What is the reason behind a Full outer Join resulting in more rows than either parent data set?

我正在处理两组数据,我试图通过 Join 命令(而不是 Union)合并它们。

我认为我不了解加入的基础知识。我使用了 Full Outer Join 如下:

    Select
      Table1.col1,
      Table1.col2, 
      Table1.date1,
      Table2.col1,
      Table2.col2,
      Table2.date2
   From Table1 full outer join 
        Table2 On Table1.date1 = Table2.date2

最终合并后的数据集的总行数大于表 1 和表 2 中行的总和。

我正在尝试理解为什么会发生这种情况。

我的印象是(CombinedTable 中的行数)=(表 1 中的行数)+(表 2 中的行数)。

为什么会出现这种情况?我该如何解决这个问题?

看看这个:

TblJob
Name, Surname, Job
John, White, Developer
John, Black, Tester
John, Grey, Manager

TblDrinksPref
Name, Surname, Drink
John, White, Coffee
John, Black, Tea
John, Grey, Orange Juice

SELECT * FROM tbljob j JOIN tbldrinkspref p ON j.name = p.name

John, White, Developer, John, White, Coffee
John, White, Developer, John, Black, Tea
John, White, Developer, John, Grey, Orange Juice
John, Black, Tester, John, White, Coffee
John, Black, Tester, John, Black, Tea
John, Black, Tester, John, Grey, Orange Juice
John, Grey, Manager, John, White, Coffee
John, Grey, Manager, John, Black, Tea
John, Grey, Manager, John, Grey, Orange Juice

通过仅加入名字,每个 table 中的每一行都与另一行匹配。每个 table 中的 3 行导致 3x3 tables 输出;大于行的总和。您将从连接中获得的最多行是进入连接的行数的乘积。我们将其称为笛卡尔积,它通常表明您的 SQL 连接中存在错误。任何连接都可以做到这一点,而不仅仅是外部连接。存在一个连接(称为 CROSS JOIN),其唯一目的是产生一个完美的笛卡尔积输出,因为有时我们确实想要这样做,但大多数情况下它表明存在问题

你能做些什么?不要将行连接到不相关的行,方法是使连接条件 better/more 准确:

SELECT * 
FROM tbljob j JOIN tbldrinkspref p 
ON j.name = p.name 
  --the last name is vital to associate rows correctly in this case
  AND j.surname = p.surname

如果您写了一个很大的 SQL 并且某些行意外重复,这意味着您的一个连接有问题。将它们全部注释掉回到第一个 table,并注释 select 块,然后在添加连接时继续重新运行 sql。当您看到行数意外增加时,这可能是失败但要注意连接也可能导致行消失,并且您可能会遇到添加连接可能导致一半行消失的情况,因为它们与连接谓词不匹配,但另一半行double 因为连接有问题。在评估添加 table 后行数应该如何变化时,您必须牢记要加入的数据,而不是它实际如何变化

您将获得 N 个示例和图表,在查看这些示例和图表之前,您应该对联接有一些了解,我假设您使用的是 MS Sql。

完全外部联接 return 是一个结果集,其中包括来自左侧和右侧的行 table,因此如果您在第一个 table 中有 3 行,在第二个中有 5 行 table,不一定只有8行。它还取决于外键值在这两个 table 之间的使用方式。

如果来自第二个 table 的值未映射到第一个 table 列值,则那些 return 为空。

如@Caius Jard 所述,return 值根据映射的值增加。希望对你有所帮助。

PS 全连接和全外连接是一样的!

考虑两个包含 m 行的表 A 和包含 n 行的 B 以及如下查询:

select count(*)
from a full join
     b
     on <some condition>;

这一行可以 return(几乎)greatest(n, m)n * m 之间的任何数字。

如果条件总是一对一(例如在 ID 上),它将 return greatest(n, m)

如果条件总是评估为 FALSE,它将 return n + m

如果条件始终评估为 TRUE,它将 return n * m

它可以 return 几乎任何介于两者之间的数字,除了少数例外(例如,在许多情况下,很难获得 n * m - 1 行)。

相比之下,INNER JOIN 可以 return 在 0n * m 行之间。

另一方面,UNION ALL 总是 return 正好是两个表中行的总和,因此您可能会混淆 UNION ALLFULL JOIN