ChatGPT解决这个技术问题 Extra ChatGPT

SQL Server:CROSS JOIN 和 FULL OUTER JOIN 有什么区别?

SQL Server 中的 CROSS JOIN 和 FULL OUTER JOIN 有什么区别?

它们是否相同?请解释。什么时候会使用其中任何一种?


D
Donnie

交叉连接在两个表之间产生一个笛卡尔积,返回所有行的所有可能组合。它没有 on 子句,因为您只是将所有内容加入到所有内容中。

full outer joinleft outerright outer 联接的组合。它返回两个表中与查询的 where 子句匹配的所有行,如果这些行不能满足 on 条件,它会将 null 值放入未填充的字段中。

这篇 wikipedia 文章通过给出一组示例表的输出示例解释了各种类型的连接。


那么在大表的情况下 FROM t1 FULL OUTER JOIN t2 ON t1.id=t2.id 总是比 FROM t1,t2 WHERE t1.id=t2.id 快?
当两个表之间的匹配项很少时,@alexkovelsky 内部连接通常更快,因为使用索引意味着它不会打扰读取其中一个表上的所有行。完全外连接必须始终读取两个表(或相关索引)中的所有行。在索引不够的情况下,或者必须读取底层堆以输出所需的列,则完全外连接几乎总是比内连接慢。
outer join 更快还是 cross join
@Shafizadeh - 他们做不同的事情。
如果我在 True 上进行 FULL OUTER JOIN 怎么办?结果/性能是否类似于 CROSS JOIN?
u
user2292493

对某些人来说可能并不总是显而易见的一件事是,与空表(或结果集)的交叉连接会导致空表(M x N;因此 M x 0 = 0)

除非 M 和 N 都为 0,否则完全外连接将始终包含行。


K
Konstantin

我想在其他答案中添加一个重要方面,它实际上以最好的方式向我解释了这个主题:

如果 2 个连接表包含 M 和 N 行,则交叉连接将始终产生 (M x N) 行,但完全外连接将产生从 MAX(M,N) 到 (M + N) 行(取决于实际行数匹配“on”谓词)。

编辑:

从逻辑查询处理的角度来看,CROSS JOIN 确实总是产生 M x N 行。 FULL OUTER JOIN 发生的情况是左右表都被“保留”,就好像 LEFT 和 RIGHT 连接都发生了一样。因此,来自左表和右表的不满足 ON 谓词的行被添加到结果集中。


这些界限是否排除了可能的 1-many 匹配?完全外连接仍然能够产生 (M x N) 行。
select COUNT_BIG(*) FROM Traffic t CROSS JOIN Recipient r 和 SELECT COUNT_BIG(*) FROM Traffic t FULL JOIN Recipient r ON (1=1) 它们是相同的。
你的答案是最好的真实答案。基本上:cross join 是表格的倍数; full outer join 在最坏的情况下添加它们,具体取决于匹配的行数。
这是错误的。 FULL JOIN ON rows 是 INNER JOIN ON rows UNION ALL 不匹配的左表行空扩展 UNION ALL 不匹配的右表行空扩展。所以 FULL JOIN 可以返回 M*N 行——可能大于 MAX(M,N) 和 M+N。但无论如何,作为 M 和 N 的函数返回的最小和最大行数是没有用的。有用的是对 FULL JOIN ON 的明确定义——就 INNER JOIN ON 和不匹配的行而言。
你能回复@philipxy 的评论吗?在我看来,philipxy 是正确的,而您的答案是不正确的。似乎外部联接(甚至内部联接)可能具有多于 M+N 行(例如,True 上的联接将等效于交叉联接并产生 M*N 行)。也许您的计算假设在具有唯一值的列上进行外部连接(例如在主键上)?还是我错过了什么?
C
Chirag

对于 SQL Server,CROSS JOIN and FULL OUTER JOIN 不同。 CROSS JOIN 只是两个表的笛卡尔积,与任何过滤条件或任何条件无关。

FULL OUTER JOIN 给出两个表的 LEFT OUTER JOIN and RIGHT OUTER JOIN 的唯一结果集。它还需要 ON 子句来映射两列表。

表 1 包含 10 行,表 2 包含 20 行,其中 5 行在特定列上匹配。然后 CROSS JOIN 将在结果集中返回 10*20=200 行。 FULL OUTER JOIN 将在结果集中返回 25 行。 INNER JOIN 将返回匹配的行,因此结果集中有 5 行。 FULL OUTER JOIN(或任何其他 JOIN)始终返回小于或等于笛卡尔积编号的结果集。 FULL OUTER JOIN 返回的行数等于(LEFT OUTER JOIN 的行数)+(RIGHT OUTER JOIN 的行数)-(INNER JOIN 的行数)。


P
Protiguous

除了返回的 NULL 值之外,它们是相同的概念。

见下文:

declare @table1 table( col1 int, col2 int );
insert into @table1 select 1, 11 union all select 2, 22;

declare @table2 table ( col1 int, col2 int );
insert into @table2 select 10, 101 union all select 2, 202;

select
    t1.*,
    t2.*
from @table1 t1
full outer join @table2 t2 on t1.col1 = t2.col1
order by t1.col1, t2.col1;

/* full outer join
col1        col2        col1        col2
----------- ----------- ----------- -----------
NULL        NULL        10          101
1           11          NULL        NULL
2           22          2           202
*/

select
    t1.*,
    t2.*
from @table1 t1
cross join @table2 t2
order by t1.col1, t2.col1;

/* cross join
col1        col2        col1        col2
----------- ----------- ----------- -----------
1           11          2           202
1           11          10          101
2           22          2           202
2           22          10          101
*/

K
KuldipMCA

交叉连接:交叉连接产生的结果由来自两个或多个表的行的每个组合组成。这意味着如果表 A 有 3 行,表 B 有 2 行,则 CROSS JOIN 将产生 6 行。这两个表之间没有建立关系——你实际上只是产生了所有可能的组合。

全外连接:全外连接既不是“左”也不是“右”——两者都是!它包括参与 JOIN 的两个表或结果集中的所有行。当 JOIN 左侧的行不存在匹配行时,您会在“右侧”的结果集中看到 Null 值。相反,当 JOIN 的“右侧”侧的行不存在匹配的行时,您会在“左侧”的结果集中看到 Null 值。


k
karaimadai

SQL 完全外连接

FULL OUTER JOIN 返回左表 (table1) 和右表 (table2) 中的所有行,与匹配无关。

FULL OUTER JOIN 关键字结合了 LEFT OUTER JOIN 和 RIGHT OUTER JOIN 的结果

SQL 全外连接也称为 FULL JOIN

参考:http://datasciencemadesimple.com/sql-full-outer-join/

SQL 交叉连接

在 SQL CROSS JOIN 中,第一个表的每一行都映射到第二个表的每一行。

CROSS JOIN 操作的结果集产生的行数等于第一个表中的行数乘以第二个表中的行数。

CROSS JOIN 也称为笛卡尔积/笛卡尔连接

表 A 中的行数为 m,表 B 中的行数为 n,结果表将有 m*n 行

参考:http://datasciencemadesimple.com/sql-cross-join/


A
Ani Menon

交叉加入http://www.dba-oracle.com/t_garmany_9_sql_cross_join.htm

TLDR;在 2 个表之间生成所有可能的组合(Carthesian 积)

(完全)外部连接http://www.w3schools.com/Sql/sql_join_full.asp

TLDR;返回两个表中的每一行以及具有相同值的结果(匹配条件)


P
Protiguous

完全外连接结合了左外连接和右外连接。结果集从两个表中返回满足条件的行,但返回不匹配的空列。

交叉连接是一种不需要任何条件来连接表的 Cartesian product。结果集包含的行和列是两个表的乘积。


S
Sergei Kuzmin

想对常见的连接类型增加直觉。想想参数化的连接伪运算符:

function generalJoin(
    forceIncludeLeft: boolean, forceIncludeRight: boolean, condition: Expression,
    tableA: Table, tableB: Table
) {
  for (leftRow in tableA) {
    for (rightRow in tableB) {
      // Output combined row if condition is true
      if (condition(leftRow, rightRow)) {
        markRowHasMatch(leftRow);
        markRowHasMatch(rightRow);
        output(leftRow.append(rightRow));
      }
    }
  }
  if (forceIncludeLeft) {
    for (leftRow in tableA) {
      if (!rowHasMatch(leftRow)) {
        output(leftRow.append(createArrayOfNulls(tableB.columnsCount)));
      }
    }
  }
  if (forceIncludeRight) {
    for (rightRow in tableB) {
      if (!rowHasMatch(rightRow)) {
        output(createArrayOfNulls(tableA.columnsCount).append(rightRow));
      }
    }
  }
}
// We may think of Expression as function taking rowA and rowB and
// returning boolean true or false
function alwaysTrue(rowA, rowB) {
  return true;
}

这相当于

[SELECT ...] from tableA SOMEJOIN tableB ON condition

那么这是等价表:

a [INNER] JOIN b ON condition       <=> generalJoin(false, false, condition, a, b)
a LEFT [OUTER] JOIN b ON condition  <=> generalJoin(true,  false, condition, a, b)
a RIGHT [OUTER] JOIN b ON condition <=> generalJoin(false, true,  condition, a, b)
a FULL [OUTER] JOIN b ON condition  <=> generalJoin(true,  true,  condition, a, b)
a CROSS JOIN b                      <=> generalJoin(false, false, alwaysTrue, a, b)

实际上,CROSS JOIN 等效于无条件的 INNER JOIN,即每个左行都匹配每个右行。