百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

SQL 如何进行并集、交集、差集等集合运算

wptr33 2025-01-06 15:47 17 浏览

目录

  • 一、什么是集合运算
  • 二、表的加法——UNION
  • 三、集合运算的注意事项
  • 四、包含重复行的集合运算——ALL 选项
  • 五、选取表中公共部分——INTERSECT
  • 六、记录的减法——EXCEPT

本文将会和大家一起学习集合运算操作。集合在数学领域表示“(各种各样的)事物的总和”,在数据库领域表示记录的集合。具体来说,表、视图和查询的执行结果都是记录的集合。

本文重点

集合运算就是对满足同一规则的记录进行的加减等四则运算。

使用 UNION(并集)、INTERSECT(交集)、EXCEPT(差集)等集合运算符来进行集合运算。

集合运算符可以去除重复行。

如果希望集合运算符保留重复性,就需要使用 ALL 选项。

一、什么是集合运算

截至目前,我们已经学习了 从表中读取数据 以及 插入数据 的方法。

所谓集合运算,就是对满足同一规则的记录进行的加减等四则运算。

通过集合运算,可以得到两张表中记录的集合或者公共记录的集合,又或者其中某张表中的记录的集合。

像这样用来进行集合运算的运算符称为集合运算符

本文将会为大家介绍表的加减法,SQL 如何使用内联结、外联结和交叉联结 将会和大家一起学习进行“表联结”的集合运算符及其使用方法-->。

二、表的加法——UNION

首先为大家介绍的集合运算符是进行记录加法运算的 UNION(并集)

在学习具体的使用方法之前,我们首先添加一张表,该表的结构与之前我们使用的 Product(商品)表相同,只是表名变为 Product2(商品 2)(代码清单 1)。

代码清单 1 创建表 Product2(商品 2)

CREATE TABLE Product2(product_id     CHAR(4)      NOT NULL, product_name   VARCHAR(100) NOT NULL, product_type   VARCHAR(32)  NOT NULL, sale_price     INTEGER      , purchase_price INTEGER      , regist_date    DATE         , PRIMARY KEY (product_id));

接下来,我们将代码清单 2 中的 5 条记录插入到 Product2 表中。

商品编号(product_id)为“0001”~“0003”的商品与之前 Product 表中的商品相同,而编号为“0009”的“手套”和“0010”的“水壶”是 Product 表中没有的商品。

代码清单 2 将数据插入到表 Product2(商品 2)中

SQL Server PostgreSQL

BEGIN TRANSACTION; ---------①INSERT INTO Product2 VALUES ('0001', 'T恤衫' ,'衣服', 1000, 500, '2009-09-20');INSERT INTO Product2 VALUES ('0002', '打孔器', '办公用品', 500, 320, '2009-09-11');INSERT INTO Product2 VALUES ('0003', '运动T恤', '衣服', 4000, 2800, NULL);INSERT INTO Product2 VALUES ('0009', '手套', '衣服', 800, 500, NULL);INSERT INTO Product2 VALUES ('0010', '水壶', '厨房用具', 2000, 1700, '2009-09-20');COMMIT;

特定的 SQL

不同的 DBMS 的事务处理的语法也不尽相同。代码清单 2 中的 DML 语句在 MySQL 中执行时,需要将 ① 部分更改为“START TRANSACTION;”。在 Oracle 和 DB2 中执行时,无需用到 ① 的部分(请删除)。

详细内容请大家参考 什么是 SQL 事务 中的“创建事务”。

这样我们的准备工作就完成了。接下来,就让我们对上述两张表进行“Product 表 + Product2 表”的加法计算吧。语法请参考代码清单 3。

代码清单 3 使用 UNION 对表进行加法运算

SELECT product_id, product_name  FROM ProductUNIONSELECT product_id, product_name  FROM Product2;

执行结果:

product_id | product_name-----------+------------- 0001      | T恤衫 0002      | 打孔器 0003      | 运动T恤 0004      | 菜刀 0005      | 高压锅 0006      | 叉子 0007      | 擦菜板 0008      | 圆珠笔 0009      | 手套 0010      | 水壶

上述结果包含了两张表中的全部商品。可能有些读者会发现,这就是我们在学校学过的集合中的并集运算,通过文氏图会看得更清晰(图 1)。

图 1 使用 UNION 对表进行加法(并集)运算的图示

商品编号为“0001”~“0003”的 3 条记录在两个表中都存在,因此大家可能会认为结果中会出现重复的记录,但是 UNION 等集合运算符通常都会除去重复的记录。

法则 1

集合运算符会除去重复的记录。

三、集合运算的注意事项

其实结果中也可以包含重复的记录,在介绍该方法之前,还是让我们先来学习一下使用集合运算符时的注意事项吧。不仅限于 UNION,之后将要学习的所有运算符都要遵守这些注意事项。

  • 注意事项 ① ——作为运算对象的记录的列数必须相同
  • 例如,像下面这样,一部分记录包含 2 列,另一部分记录包含 3 列时会发生错误,无法进行加法运算。
  • -- 列数不一致时会发生错误SELECT product_id, product_nameFROM ProductUNIONSELECT product_id, product_name, sale_priceFROM Product2;
  • 注意事项 ②——作为运算对象的记录中列的类型必须一致
  • 从左侧开始,相同位置上的列必须是同一数据类型。
  • 例如下面的 SQL 语句,虽然列数相同,但是第 2 列的数据类型并不一致(一个是数值类型,一个是日期类型),因此会发生错误 [1]。
  • -- 数据类型不一致时会发生错误SELECT product_id, sale_priceFROM ProductUNIONSELECT product_id, regist_dateFROM Product2;
  • 一定要使用不同数据类型的列时,可以使用 SQL 常用的函数 中的类型转换函数 CAST
  • 注意事项 ③——可以使用任何 SELECT 语句,但 ORDER BY 子句只能在最后使用一次
  • 通过 UNION 进行并集运算时可以使用任何形式的 SELECT 语句,之前学过的 WHEREGROUP BYHAVING 等子句都可以使用。
  • 但是 ORDER BY 只能在最后使用一次(代码清单 4)。
  • 代码清单 4 ORDER BY 子句只在最后使用一次
  • SELECT product_id, product_nameFROM ProductWHERE product_type = '厨房用具'UNIONSELECT product_id, product_nameFROM Product2WHERE product_type = '厨房用具'ORDER BY product_id;
  • 执行结果:
  • product_id | product_name-----------+--------------0004 | 菜刀0005 | 高压锅0006 | 叉子0007 | 擦菜板0010 | 水壶

四、包含重复行的集合运算——ALL 选项

接下来给大家介绍在 UNION 的结果中保留重复行的语法。其实非常简单,只需要在 UNION 后面添加 ALL 关键字就可以了。

这里的 ALL 选项,在 UNION 之外的集合运算符中同样可以使用(代码清单 5)。

代码清单 5 保留重复行

SELECT product_id, product_name  FROM ProductUNION ALLSELECT product_id, product_name  FROM Product2;

执行结果:

法则 2

在集合运算符中使用 ALL 选项,可以保留重复行。

五、选取表中公共部分——INTERSECT

下面将要介绍的集合运算符在数的四则运算中并不存在,不过也不难理解,那就是选取两个记录集合中公共部分的 INTERSECT(交集) [2]。

让我们赶快来看一下吧。其语法和 UNION 完全一样(代码清单 6)。

代码清单 6 使用 INTERSECT 选取出表中公共部分

Oracle SQL Server DB2 PostgreSQL

SELECT product_id, product_name  FROM ProductINTERSECTSELECT product_id, product_name  FROM Product2ORDER BY product_id;

执行结果:

 product_id | product_name------------+-------------- 0001       | T恤衫 0002       | 打孔器 0003       | 运动T恤

大家可以看到,结果中只包含两张表中记录的公共部分。该运算的文氏图如下所示(图 2)。

图 2 使用 INTERSECT 选取出表中公共部分的图示

与使用 AND 可以选取出一张表中满足多个条件的公共部分不同,INTERSECT 应用于两张表,选取出它们当中的公共记录

其注意事项与 UNION 相同,我们在“集合运算的注意事项”和“保留重复行的集合运算”中已经介绍过了。希望保留重复行时同样需要使用 INTERSECT ALL

六、记录的减法——EXCEPT

最后要给大家介绍的集合运算符就是进行减法运算的 EXCEPT(差集)[3],其语法也与UNION 相同(代码清单 7)。

代码清单 7 使用 EXCEPT 对记录进行减法运算

SQL Server DB2 PostgreSQL

SELECT product_id, product_name  FROM ProductEXCEPTSELECT product_id, product_name  FROM Product2ORDER BY product_id;

特定的 SQL

在 Oracle 中执行代码清单 7 或者代码清单 8 中的 SQL 时,请将 EXCEPT 改为 MINUS

-- Oracle中使用MINUS而不是EXCEPT SELECT … FROM … MINUS SELECT … FROM …;

执行结果:

product_id | product_name-----------+-------------- 0004      | 菜刀 0005      | 高压锅 0006      | 叉子 0007      | 擦菜板 0008      | 圆珠笔

大家可以看到,结果中只包含 Product 表中记录除去 Product2 表中记录之后的剩余部分。该运算的文氏图如图 3 所示。

图 3 使用 EXCEPT 对记录进行减法运算的图示

EXCEPT 有一点与 UNIONINTERSECT 不同,需要注意一下。

那就是在减法运算中减数和被减数的位置不同,所得到的结果也不相同。4 + 22 + 4 的结果相同,但是 4 - 22 - 4 的结果却不一样。

因此,我们将之前 SQL 中的 ProductProduct2 互换,就能得到代码清单 8 中的结果。

代码清单 8 被减数和减数位置不同,得到的结果也不同

SQL Server DB2 PostgreSQL

-- 从Product2的记录中除去Product中的记录SELECT product_id, product_name  FROM Product2EXCEPTSELECT product_id, product_name  FROM ProductORDER BY product_id;

执行结果:

 product_id | product_name------------+-------------- 0009       | 手套 0010       | 水壶

上述运算的文氏图如图 4 所示。

图 4 使用 EXCEPT 对记录进行减法运算的图示(从 Product2 中除去 Product 中的记录)

到此,对 SQL 提供的集合运算符的学习已经结束了。

可能有些读者会想“唉?怎么没有乘法和除法呢?”关于乘法的相关内容,我们将在 SQL 如何使用内联结、外联结和交叉联结 详细介绍。

此外,SQL 中虽然也存在除法,但由于除法是比较难理解的运算,属于中级内容,因此我们会在 SQL 如何使用内联结、外联结和交叉联结 末尾的专栏中进行一些简单的介绍,感兴趣的读者请参考专栏“关系除法”。


  1. 实际上,在有些 DBMS 中,即使数据类型不同,也可以通过隐式类型转换来完成操作。但由于并非所有的 DBMS 都支持这样的用法,因此还是希望大家能够使用恰当的数据类型来进行运算。 ??
  2. 因为 MySQL 尚不支持 INTERSECT,所以无法使用。 ??
  3. 只有 Oracle 不使用 EXCEPT,而是使用其特有的 MINUS 运算符。使用 Oracle 的用户,请用 MINUS 代替 EXCEPT。此外,MySQL 还不支持 EXCEPT,因此也无法使用。 ??

相关推荐

Python自动化脚本应用与示例(python办公自动化脚本)

Python是编写自动化脚本的绝佳选择,因其语法简洁、库丰富且跨平台兼容性强。以下是Python自动化脚本的常见应用场景及示例,帮助你快速上手:一、常见自动化场景文件与目录操作...

Python文件操作常用库高级应用教程

本文是在前面《Python文件操作常用库使用教程》的基础上,进一步学习Python文件操作库的高级应用。一、高级文件系统监控1.1watchdog库-实时文件系统监控安装与基本使用:...

Python办公自动化系列篇之六:文件系统与操作系统任务

作为高效办公自动化领域的主流编程语言,Python凭借其优雅的语法结构、完善的技术生态及成熟的第三方工具库集合,已成为企业数字化转型过程中提升运营效率的理想选择。该语言在结构化数据处理、自动化文档生成...

14《Python 办公自动化教程》os 模块操作文件与文件夹

在日常工作中,我们经常会和文件、文件夹打交道,比如将服务器上指定目录下文件进行归档,或将爬虫爬取的数据根据时间创建对应的文件夹/文件,如果这些还依靠手动来进行操作,无疑是费时费力的,这时候Pyt...

python中os模块详解(python os.path模块)

os模块是Python标准库中的一个模块,它提供了与操作系统交互的方法。使用os模块可以方便地执行许多常见的系统任务,如文件和目录操作、进程管理、环境变量管理等。下面是os模块中一些常用的函数和方法:...

21-Python-文件操作(python文件的操作步骤)

在Python中,文件操作是非常重要的一部分,它允许我们读取、写入和修改文件。下面将详细讲解Python文件操作的各个方面,并给出相应的示例。1-打开文件...

轻松玩转Python文件操作:移动、删除

哈喽,大家好,我是木头左!Python文件操作基础在处理计算机文件时,经常需要执行如移动和删除等基本操作。Python提供了一些内置的库来帮助完成这些任务,其中最常用的就是os模块和shutil模块。...

Python 初学者练习:删除文件和文件夹

在本教程中,你将学习如何在Python中删除文件和文件夹。使用os.remove()函数删除文件...

引人遐想,用 Python 获取你想要的“某个人”摄像头照片

仅用来学习,希望给你们有提供到学习上的作用。1.安装库需要安装python3.5以上版本,在官网下载即可。然后安装库opencv-python,安装方式为打开终端输入命令行。...

Python如何使用临时文件和目录(python目录下文件)

在某些项目中,有时候会有大量的临时数据,比如各种日志,这时候我们要做数据分析,并把最后的结果储存起来,这些大量的临时数据如果常驻内存,将消耗大量内存资源,我们可以使用临时文件,存储这些临时数据。使用标...

Linux 下海量文件删除方法效率对比,最慢的竟然是 rm

Linux下海量文件删除方法效率对比,本次参赛选手一共6位,分别是:rm、find、findwithdelete、rsync、Python、Perl.首先建立50万个文件$testfor...

Python 开发工程师必会的 5 个系统命令操作库

当我们需要编写自动化脚本、部署工具、监控程序时,熟练操作系统命令几乎是必备技能。今天就来聊聊我在实际项目中高频使用的5个系统命令操作库,这些可都是能让你效率翻倍的"瑞士军刀"。一...

Python常用文件操作库使用详解(python文件操作选项)

Python生态系统提供了丰富的文件操作库,可以处理各种复杂的文件操作需求。本教程将介绍Python中最常用的文件操作库及其实际应用。一、标准库核心模块1.1os模块-操作系统接口主要功能...

11. 文件与IO操作(文件io和网络io)

本章深入探讨Go语言文件处理与IO操作的核心技术,结合高性能实践与安全规范,提供企业级解决方案。11.1文件读写11.1.1基础操作...

Python os模块的20个应用实例(python中 import os模块用法)

在Python中,...