主頁 > 資料庫 > SQL 如何進行并集、交集、差集等集合運算

SQL 如何進行并集、交集、差集等集合運算

2022-07-14 10:17:12 資料庫

目錄
  • 一、什么是集合運算
  • 二、表的加法——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 Product
UNION
SELECT product_id, product_name
  FROM Product2;

執行結果:

product_id | product_name
-----------+-------------
 0001      | T恤衫
 0002      | 打孔器
 0003      | 運動T恤
 0004      | 菜刀
 0005      | 高壓鍋
 0006      | 叉子
 0007      | 擦菜板
 0008      | 圓珠筆
 0009      | 手套
 0010      | 水壺

上述結果包含了兩張表中的全部商品,可能有些讀者會發現,這就是我們在學校學過的集合中的并集運算,通過文氏圖會看得更清晰(圖 1),

使用 UNION 對表進行加法(并集)運算的圖示

圖 1 使用 UNION 對表進行加法(并集)運算的圖示

商品編號為“0001”~“0003”的 3 條記錄在兩個表中都存在,因此大家可能會認為結果中會出現重復的記錄,但是 UNION 等集合運算子通常都會除去重復的記錄,

法則 1

集合運算子會除去重復的記錄,

三、集合運算的注意事項

其實結果中也可以包含重復的記錄,在介紹該方法之前,還是讓我們先來學習一下使用集合運算子時的注意事項吧,不僅限于 UNION,之后將要學習的所有運算子都要遵守這些注意事項,

  • 注意事項 ① ——作為運算物件的記錄的列數必須相同

    例如,像下面這樣,一部分記錄包含 2 列,另一部分記錄包含 3 列時會發生錯誤,無法進行加法運算,

    -- 列數不一致時會發生錯誤
    SELECT product_id, product_name
    FROM Product
    UNION
    SELECT product_id, product_name, sale_price
    FROM Product2;
    
  • 注意事項 ②——作為運算物件的記錄中列的型別必須一致

    從左側開始,相同位置上的列必須是同一資料型別,

    例如下面的 SQL 陳述句,雖然列數相同,但是第 2 列的資料型別并不一致(一個是數值型別,一個是日期型別),因此會發生錯誤 [1]

    -- 資料型別不一致時會發生錯誤
    SELECT product_id, sale_price
    FROM Product
    UNION
    SELECT product_id, regist_date
    FROM Product2;
    

    一定要使用不同資料型別的列時,可以使用 SQL 常用的函式 中的型別轉換函式 CAST

  • 注意事項 ③——可以使用任何 SELECT 陳述句,但 ORDER BY 子句只能在最后使用一次

    通過 UNION 進行并集運算時可以使用任何形式的 SELECT 陳述句,之前學過的 WHEREGROUP BYHAVING 等子句都可以使用,

    但是 ORDER BY 只能在最后使用一次(代碼清單 4),

    代碼清單 4 ORDER BY 子句只在最后使用一次

    SELECT product_id, product_name
    FROM Product
    WHERE product_type = '廚房用具'
    UNION
    SELECT product_id, product_name
    FROM Product2
    WHERE 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 Product
UNION ALL
SELECT 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 Product
INTERSECT
SELECT product_id, product_name
  FROM Product2
ORDER BY product_id;

執行結果:

 product_id | product_name
------------+--------------
 0001       | T恤衫
 0002       | 打孔器
 0003       | 運動T恤

大家可以看到,結果中只包含兩張表中記錄的公共部分,該運算的文氏圖如下所示(圖 2),

使用 INTERSECT 選取出表中公共部分的圖示

圖 2 使用 INTERSECT 選取出表中公共部分的圖示

與使用 AND 可以選取出一張表中滿足多個條件的公共部分不同,INTERSECT 應用于兩張表,選取出它們當中的公共記錄

其注意事項與 UNION 相同,我們在“集合運算的注意事項”和“保留重復行的集合運算”中已經介紹過了,希望保留重復行時同樣需要使用 INTERSECT ALL

六、記錄的減法——EXCEPT

最后要給大家介紹的集合運算子就是進行減法運算的 EXCEPT(差集)[3],其語法也與UNION 相同(代碼清單 7),

代碼清單 7 使用 EXCEPT 對記錄進行減法運算

SQL Server DB2 PostgreSQL

SELECT product_id, product_name
  FROM Product
EXCEPT
SELECT product_id, product_name
  FROM Product2
ORDER 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 所示,

使用 EXCEPT 對記錄進行減法運算的圖示

圖 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 Product2
EXCEPT
SELECT product_id, product_name
  FROM Product
ORDER BY product_id;

執行結果:

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

上述運算的文氏圖如圖 4 所示,

使用 EXCEPT 對記錄進行減法運算的圖示(從 Product2 中除去 Product 中的記錄)

圖 4 使用 EXCEPT 對記錄進行減法運算的圖示(從 Product2 中除去 Product 中的記錄)

到此,對 SQL 提供的集合運算子的學習已經結束了,

可能有些讀者會想“唉?怎么沒有乘法和除法呢?”關于乘法的相關內容,我們將在 SQL 如何使用行內結、外聯結和交叉聯結 詳細介紹,

此外,SQL 中雖然也存在除法,但由于除法是比較難理解的運算,屬于中級內容,因此我們會在 SQL 如何使用行內結、外聯結和交叉聯結 末尾的專欄中進行一些簡單的介紹,感興趣的讀者請參考專欄“關系除法”,

原文鏈接:https://www.developerastrid.com/sql/sql-union-intersect-except/

(完)


  1. 實際上,在有些 DBMS 中,即使資料型別不同,也可以通過隱式型別轉換來完成操作,但由于并非所有的 DBMS 都支持這樣的用法,因此還是希望大家能夠使用恰當的資料型別來進行運算, ??

  2. 因為 MySQL 尚不支持 INTERSECT,所以無法使用, ??

  3. 只有 Oracle 不使用 EXCEPT,而是使用其特有的 MINUS 運算子,使用 Oracle 的用戶,請用 MINUS 代替 EXCEPT,此外,MySQL 還不支持 EXCEPT,因此也無法使用, ??

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/499176.html

標籤:SQL Server

上一篇:除錯Archery連接SQL Server提示驅動錯誤

下一篇:SQL 如何使用行內結、外聯結和交叉聯結

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more