新特性解讀 | MySQL 8.0 的交集和差集介紹

作者:楊濤濤

資深資料庫專家,專研 MySQL 十餘年。擅長 MySQL、PostgreSQL、MongoDB 等開源資料庫相關的備份恢復、SQL 調優、監控運維、高可用架構設計等。目前任職於愛可生,為各大運營商及銀行金融企業提供 MySQL 相關技術支援、MySQL 相關課程培訓等工作。

本文來源:原創投稿

MySQL 8。0 最新小版本(8。0。31)支援標準SQL 的intersect(交集)和except(差集)操作。

交集: 也就是返回兩個結果集的相交部分,也即左側和右側同時存在的記錄。

差集:也就是返回兩個結果集中左側存在同時右側不存在的記錄。

之前在做其他資料庫往MySQL遷移的時候,經常遇到這樣的操作。由於MySQL 一直以來不支援這兩類運算子,一般得想辦法避開或者是透過其他方法來實現。

比如在MySQL 5.7.x 中,想要實現如下兩個需求:

第一、求表t1和表t2的交集,並且結果要去重;

第二、求表t1和表t2的差集,並且結果也要去重。

簡單建立表t1、表t2,並且插入幾條樣例資料:

create table t1(c1 int);Query OK, 0 rows affected (0。02 sec) create table t2 like t1;Query OK, 0 rows affected (0。02 sec) insert t1 values (10),(20),(20),(30),(40),(40),(50);Query OK, 7 rows affected (0。00 sec)Records: 7 Duplicates: 0 Warnings: 0 insert t2 values (10),(30),(30),(50),(50),(70),(90);Query OK, 7 rows affected (0。02 sec)Records: 7 Duplicates: 0 Warnings: 0 select * from t1;+————+| c1 |+————+| 10 || 20 || 20 || 30 || 40 || 40 || 50 |+————+7 rows in set (0。00 sec) select * from t2;+————+| c1 |+————+| 10 || 30 || 30 || 50 || 50 || 70 || 90 |+————+7 rows in set (0。00 sec)

我們來實現這兩個需求:

求去重後的交集: 兩表內聯、去重!

select distinct t1。c1 from t1 join t2 using(c1);+————+| c1 |+————+| 10 || 30 || 50 |+————+3 rows in set (0。00 sec)

求去重後的差集:兩表左外聯,去重,並且保留右表關聯鍵為NULL的記錄。

select distinct t1。c1 from t1 left join t2 using(c1) where t2。c1 is null;+————+| c1 |+————+| 20 || 40 |+————+2 rows in set (0。00 sec)

在最新版本MySQL 8。0。31中,直接用intersect 和except兩個新運算子即可,寫起來非常簡單。

建立好同樣的表結構和資料,用intersect來求交集:

table t1 intersect table t2;+————+| c1 |+————+| 10 || 30 || 50 |+————+3 rows in set (0。00 sec)

用except來求差集:

table t1 except table t2;+————+| c1 |+————+| 20 || 40 |+————+2 rows in set (0。00 sec)

intersect 和except運算子預設去重。比如需要保留原始結果,則可以帶上all 關鍵詞: 如下求兩表差集的結果會保留所有符合條件的記錄。

table t1 except all table t2;+————+| c1 |+————+| 20 || 20 || 40 || 40 |+————+4 rows in set (0。00 sec)