跳转到主要内容
模块 5 · 第 4 课(共 4)课程中的20/57~12 min
模块课程(4/4)

并集、相交、例外(和交叉连接)

到目前为止,您已经水平合并了数据:JOIN 附加列 来自相关行。 SQL 还提供了另一系列运算符 垂直组合数据,将两个 SELECT 的结果视为 集:UNION、INTERSECT、EXCEPT。我们还回顾了 CROSS JOIN, 笛卡尔积。

CROSS JOIN:每一行与每一行

CROSS JOIN 没有 ON:它产生 所有可能的组合 两个表之间的行(笛卡尔积)。如果 A 有 n 行且 B 有 m 行,结果有 n × m。

SQL
-- Tutte le combinazioni cliente × prodotto:
SELECT c.email, p.name
FROM   customers c
CROSS JOIN products p;

12 个客户 × 16 个产品 = 192 行。它很少用于真实数据(它是 昂贵!),但它有以下用途:

  • 生成“全部对抗全部”组合(例如兼容性矩阵);
  • 将一个表与一个小常量/参数表配对。

联合和联合全部

UNION 将两个具有 相同编号的 SELECT 的结果附加到一起 列类型:

SQL
SELECT email FROM customers WHERE country = 'Italia'
UNION
SELECT email FROM customers WHERE country = 'Francia';

规则:

  • 两个 SELECT 必须具有相同的列数,并且兼容 类型;
  • UNION(没有 ALL)删除重复项 — 有效地执行 DISTINCT 最终结果;
  • UNION ALL 也保留重复项,并且快得多,因为它 避免重复数据删除的排序/散列。
SQL
-- Email di clienti che hanno ordinato O recensito qualcosa, senza duplicati:
SELECT c.email
FROM   customers c JOIN orders  o ON o.customer_id = c.id
UNION
SELECT c.email
FROM   customers c JOIN reviews r ON r.customer_id = c.id;

相交和除外

INTERSECT 仅保留两个结果中都存在的行; EXCEPT 保留第一个不在第二个中的行(集合 “差异”)。

SQL
-- Clienti che hanno sia ordinato sia recensito:
SELECT c.email FROM customers c JOIN orders  o ON o.customer_id = c.id
INTERSECT
SELECT c.email FROM customers c JOIN reviews r ON r.customer_id = c.id;

-- Clienti che hanno ordinato ma mai recensito:
SELECT c.email FROM customers c JOIN orders  o ON o.customer_id = c.id
EXCEPT
SELECT c.email FROM customers c JOIN reviews r ON r.customer_id = c.id;

INTERSECT 和 EXCEPT 默认情况下也会删除重复项;的 INTERSECT ALL / EXCEPT ALL 变体则不然。

自己尝试一下

锻炼#sql.m5.l4.e1
尝试:0加载中...

Trova tutte le email dei clienti che hanno ordinato qualcosa OPPURE recensito qualcosa (senza duplicati). Una colonna:电子邮件。 Ordina 每封电子邮件。

正在加载编辑器...
显示提示

返回同一电子邮件列的两个 SELECT 之间的 UNION。 ORDER BY 位于最后,即最终结果。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m5.l4.e2
尝试:0加载中...

客户发来的电子邮件是我的客户,但我无法接受。美国除外。 Una colonna:电子邮件。 Ordina 每封电子邮件。

正在加载编辑器...
显示提示

EXCEPT 仅保留左侧 SELECT 中不存在于右侧 SELECT 中的行。

3 次尝试后可用的解决方案