這篇文章說一個關于
ORACLE
中的
UNION
、
UNION ALL
、
INTERSECT
、
MINUS
的解釋和用法:
先建立一張
TABLE
,用來做實驗:
建表語句如下所示:
create table student
(
id int primary key,
name nvarchar2(50) not null,
score number not null
);
insert into student values(1,'zhangsan',78);
insert into student values(2,'lisi',76);
insert into student values(3,'wangwu',89);
insert into student values(4,'zhaoliu',90);
insert into student values(5,'xiaohua',73);
insert into student values(6,'xiaoming',61);
insert into student values(7,'xiaoli',99);
insert into student values(8,'wangmazi',56);
insert into student values(9,'huqingniu',93);
insert into student values(10,'zhangwuji',90);
commit;
檢視插入表中的所有資料:
SELECT * FROM STUDENT;
結果如下圖所示:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLzYjNwEzNxUTM4ETNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
(1)使用
UNION
對兩個結果集進行連接配接,
SQL
如下所示,結果如下圖所示
SELECT * FROM STUDENT T
WHERE T.ID<4
UNION
SELECT * FROM STUDENT T
WHERE T.ID>2 AND T.ID<6;
通過上圖我們可以看出來,使用
UNION
傳回了5條資料。
(2)使用
UNION ALL
對兩個結果集連接配接,
SQL
如下所示,結果如下圖所示:
SELECT * FROM STUDENT T
WHERE T.ID<4
UNION ALL
SELECT * FROM STUDENT T
WHERE T.ID>2 AND T.ID<6;
通過上圖我們可以看出來,使用
UNION ALL
傳回了6條資料,與(1)中的結果相比,多了一條
ID
為3的資料。
為什麼會這樣,我們看一下我們的
SQL
,我們的語句是由兩部分查詢結果集進行組合的,是以分别單獨看一下每一部分的
SQL
:
第一部分:
SELECT * FROM STUDENT T WHERE T.ID<4
這句
SQL
會傳回
ID
小于4的記錄,單獨執行應該傳回3條資料,
ID
為1,2,3的記錄
第二部分:
SELECT * FROM STUDENT T WHERE T.ID>2 AND T.ID<6
這句
SQL
會傳回
ID
大于2小于6的記錄,也就是3條記錄,
ID
為3,4,5的記錄
當我們使用
UNION
的時候,傳回的記錄
ID
分别為1,2,3,4,5,并不是上面分析的兩部分直接組合,而是将兩部分中相同的記錄進行了去重,隻留下重複記錄中的一條資料。
當我們使用
UNION ALL
的時候,傳回的記錄
ID
分别是1,2,3,3,4,5,是兩部分的記錄集直接組合,并沒有對重複的記錄進行去重。
是以通過上面這個例子,我們可以知道:
UNION
會對記錄集中重複記錄去重,
UNION ALL
不會對記錄集中的重複記錄去重,是以在寫
SQL
文的時候,需要考慮到底是需要去重還是不去重,去重選擇前者,不去重選擇後者,當然如果選擇前者的話,那麼
SQL
性能會低于後者,因為後者隻是對記錄的展示,而前者需要對查詢的記錄集中的重複記錄進行去重,多了一個步驟,是以會影響
SQL
的性能。
(3)對于(1)和(2)中的
SQL
連接配接順序調整一下,原來是先篩選
ID
小于4的記錄集連接配接篩選
ID
大于2小于6的記錄集,現在我們颠倒一下,
SQL
如下圖所示:
SELECT * FROM STUDENT T
WHERE T.ID>2 AND T.ID<6
UNION
SELECT * FROM STUDENT T
WHERE T.ID<4;
結果如圖所示:
SELECT * FROM STUDENT T
WHERE T.ID>2 AND T.ID<6
UNION ALL
SELECT * FROM STUDENT T
WHERE T.ID<4;
結果如圖所示:
通過(3)中的第一段
SQL
和結果圖檔,可以看到傳回了5條記錄,但是細心點可以發現它傳回的記錄進行了排序,因為我們
SQL
寫的是先篩選
ID
大于2小于6的,但是結果卻和我們預想的不一樣;第2段
SQL
,傳回了6條記錄,按照我們預想的一樣,記錄集的
ID
是3,4,5,1,2,3,
SQL
是怎麼寫的,結果集就按照其進行輸出。
通過(3),我們應該可以發現,
UNION
會對記錄集進行排序,
UNION ALL
不會對記錄集進行排序。
(4)從(3)中知道了使用
UNION
的話,會對結果集進行排序,我們從(3)中第一段
SQL
結果集發現是按照
ID
進行升序排序的,那麼為什麼會按照
ID
進行排序,我們試圖修改一下
SQL
,再看是否還是按照
ID
排序:
修改後的
SQL
文:
SELECT T.SCORE,T.ID,T.NAME FROM STUDENT T
WHERE T.ID>2 AND T.ID<6
UNION
SELECT T.SCORE,T.ID,T.NAME FROM STUDENT T
WHERE T.ID<4;
對應的記錄集如下圖所示:
通過這個記錄集,可以發現,這個查詢記錄是按照
SCORE
進行排序的,那麼我們就可以認為,
UNION
的排序,是按照查詢列的字段名字順序排序的,比如
SELECT COLUMN1,COLUMN2,COLUMN3 FROM TABLENAME T
UNION
SELECT COLUMN1,COLUMN2,COLUMN3 FROM TABLENAME T
結果集就是按照
ORDER BY COLUMN1,COLUMN2,COLUMN3
進行排序的。
為了驗證上面我們的說話,
UNION
會按照查詢的列的字段名字升序排序,下面再看一個例子:
SELECT SCORE, ID, NAME
FROM STUDENT
WHERE ID > 2
UNION
SELECT SCORE, ID, NAME
FROM STUDENT
WHERE ID < 4
結果如圖所示:
通過上圖可以看出,的确是按照查詢字段進行排序,當第一個排序字段值相同的時候,按照第二個字段的值進行排序,以此類推。
如果我們需要讓查詢記錄集按照我們的要求進行排序,那麼就需要在整段
SQL
的末尾寫上
ORDER BY COLUMNS
,這樣的話,記錄集就是按照我們的要求進行排序的,測試如下:
SELECT SCORE, ID, NAME
FROM STUDENT
WHERE ID > 2
UNION
SELECT SCORE, ID, NAME
FROM STUDENT
WHERE ID < 4
ORDER BY ID DESC
運作結果如圖所示:
總結:
-
會對記錄集中的重複記錄進行去重,并且會按照查詢的字段列進行預設升序排序UNION
-
不會對記錄集中的重複記錄進行去重,隻會将查詢記錄組合顯示出來,也不會進行排序UNION ALL
- 使用
的記錄集需要排序,可以在UNION
的最末端,寫SQL
,你需要排序的字段名稱ORDER BY COLUMNS
-
對兩個結果集進行交集操作,不包括重複行,同時進行預設規則的排序Intersect
-
對兩個結果集進行差操作,不包括重複行,同時進行預設規則的排序Minus