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

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

mhr18 2024-10-05 17:54 55 浏览 0 评论

目录

  • 一、什么是集合运算
  • 二、表的加法——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,因此也无法使用。 ??

相关推荐

甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入

IT之家7月1日消息,根据甲骨文Oracle当地时间6月30日向美国证券交易委员会(SEC)递交的FORM8-K文件,该企业在始于2025年6月1日的202...

甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云

IT之家6月23日消息,Oracle甲骨文创始人、董事长兼首席技术官LarryEllison(拉里埃里森)在本月早些时候的2025财年第四财季和全财年财报电话会议上表示,Oracle...

Spring Boot 自定义数据源设置,这些坑你踩过吗?

你在使用SpringBoot进行后端开发的过程中,是不是也遇到过这样的问题:项目上线后,数据库连接总是不稳定,偶尔还会出现数据读取缓慢的情况,严重影响了用户体验。经过排查,发现很大一部分原因竟然...

一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)

今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...

低代码建模平台-数据挖掘平台(低代码平台的实现方式)

现在来看一下数据连接。·这里是管理数据连接的空间,点击这里可以新增一个数据连接。·输入连接名称,然后输入url,是通过gdbc的方式去连接的数据库,目前是支持mysql、oracle以及国产数据库达梦...

navicat 17.2.7连接oracle数据库提示加载oracle库失败

系统:macOS15.5navicat版本:navicatpremiumlite17.2.7连接oracle测试报错:加载oracle库失败【解决办法】:放达里面找到程序,显示简介里面勾选“使...

开源“Windows”ReactOS更新:支持全屏应用

IT之家6月17日消息,ReactOS团队昨日(6月16日)在X平台发布系列推文,公布了该系统的最新进展,包括升级Explorer组件,支持全屏应用,从Wine项目引入了...

SSL 推出采用全模拟内置混音技术的模拟调音台Oracle

英国调音台传奇品牌SolidStateLogic宣布推出Oracle——一款采用全模拟内置混音技术的调音台,在紧凑的AWS尺寸机箱内集成了大型调音台的功能。该调音台提供24输入和...

47道网络工程师常见面试题,看看有没有你不会的!

你们好,我的网工朋友。网络工程师面试的时候,都会被问到什么?这个问题其实很泛,一般来说,你肯定要先看明白岗位需求写的是什么。基本上都是围绕公司需要的业务去问的。但不可否认的是,那些最基础的概念,多少也...

汉得信息:发布EBS系统安装启用JWS的高效解决方案

e公司讯,从汉得信息获悉,近日,微软官方宣布InternetExplorer桌面应用程序将于2022年6月15日正式停用。目前大部分客户都是使用IE浏览器打开EBS的Form界面,IE停用后,只能使...

36.9K star ! 推荐一个酷炫低代码开发平台!功能太强!

前言最近在逛github,看看能不能搜罗到一些对自己有帮助的开源软件。不经意间看到一个高star的java开源项目:jeecg-boot。进入在线演示版一看,感叹实在是太牛了!此开源项目不管是给来学习...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

手把手教你在嵌入式设备中使用SQLite3

摘要:数据库是用来存储和管理数据的专用软件,使得管理数据更加安全,方便和高效。数据库对数据的管理的基本单位是表(table),在嵌入式linux中有时候它也需要用到数据库,听起来好难,其实就是几个函数...

JAVA语言基础(java语言基础知识)

一、计算机的基本概念什么是计算机?计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行、自动高速处理海量数据的现代化智能电子设备。由硬件和软件组成、没有安装过任何软件的计算机称...

再见 Navicat!一款开源的 Web 数据库管理工具!

大家好,我是Java陈序员。在日常的开发工作中,常常需要与各种数据库打交道。而为了提高工作效率,常常会使用一些可视化工具进行操作数据库。今天,给大家介绍一款开源的数据库管理工具,无需下载安装软件,基...

取消回复欢迎 发表评论: