本文介紹如何利用 SQL UNION 操作符將多條 SELECT 語句組合成一個結果集。使用 UNION 可極大地簡化複雜的 WHERE 子句,簡化從多個表中檢索數據的工作。 一、組合查詢 多數 SQL 查詢只包含從一個或多個表中返回數據的單條 SELECT 語句。但是,SQL 也允許執行多個查詢( ...
目錄
本文介紹如何利用 SQL UNION
操作符將多條 SELECT 語句組合成一個結果集。使用 UNION
可極大地簡化複雜的 WHERE
子句,簡化從多個表中檢索數據的工作。
一、組合查詢
多數 SQL 查詢只包含從一個或多個表中返回數據的單條 SELECT
語句。但是,SQL 也允許執行多個查詢(多條 SELECT
語句),並將結果作為一個查詢結果集返回。
這些組合查詢通常稱為並(union)或複合查詢(compound query)。
主要有兩種情況需要使用組合查詢:
- 在一個查詢中從不同的表返回結構數據;
- 對一個表執行多個查詢,按一個查詢返回數據。
提示:組合查詢和多個
WHERE
條件多數情況下,組合相同表的兩個查詢所完成的工作與具有多個
WHERE
子句條件的一個查詢所完成的工作相同。換句話說,任何具有多個
WHERE
子句的SELECT
語句都可以作為一個組合查詢,在下麵可以看到這一點。
二、創建組合查詢
可用 UNION
操作符來組合數條 SQL 查詢。利用 UNION
,可給出多條 SELECT
語句,將它們的結果組合成一個結果集。
2.1 使用 UNION
使用 UNION
很簡單,所要做的只是給出每條 SELECT
語句,在各條語句之間放上關鍵字 UNION
。
舉個例子,假如需要 Illinois
、Indiana
和 Michigan
等美國幾個州的所有顧客的報表,還想包括不管位於哪個州的所有的 Fun4All
。
當然可以利用 WHERE
子句來完成此工作,不過這次我們使用 UNION
。
如上所述,創建 UNION
涉及編寫多條 SELECT
語句。首先來看單條語句:
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI');
輸出:
cust_name cust_contact cust_email
----------- ------------- ------------
Village Toys John Smith [email protected]
Fun4All Jim Jones [email protected]
The Toy Store Kim Howard NULL
輸入:
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
輸出:
cust_name cust_contact cust_email
----------- ------------- ------------
Fun4All Jim Jones [email protected]
Fun4All Denise L. Stephens [email protected]
第一條 SELECT
把 Illinois
、Indiana
、Michigan
等州的縮寫傳遞給 IN
子句,檢索出這些州的所有行。
第二條 SELECT
利用簡單的相等測試找出所有 Fun4All
。你會發現有一條記錄出現在兩次結果里,因為它滿足兩次的條件。
組合這兩條語句,可以如下進行:
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
輸出:
cust_name cust_contact cust_email
----------- ----------- ----------------
Fun4All Denise L. Stephens [email protected]
Fun4All Jim Jones [email protected]
Village Toys John Smith [email protected]
The Toy Store Kim Howard NULL
這條語句由前面的兩條 SELECT
語句組成,之間用 UNION
關鍵字分隔。UNION
指示 DBMS 執行這兩條 SELECT
語句,並把輸出組合成一個查詢結果集。
為了便於參考,這裡給出使用多條 WHERE
子句而不是 UNION
的相同查詢:
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI') OR cust_name='Fun4All';
在這個簡單的例子中,使用 UNION
可能比使用 WHERE
子句更為複雜。但對於較複雜的過濾條件,或者從多個表(而不是一個表)中檢索數據的情形,使用 UNION
可能會使處理更簡單。
提示:
UNION
的限制使用
UNION
組合SELECT
語句的數目,SQL 沒有標準限制。但是,最好是參考一下具體的 DBMS 文檔,瞭解它是否對UNION
能組合的最大語句數目有限制。
註意:性能問題
多數好的 DBMS 使用內部查詢優化程式,在處理各條
SELECT
語句前組合它們。理論上講,這意味著從性能上看使用多條
WHERE
子句條件還是UNION
應該沒有實際的差別。不過我說的是理論上,實踐中多數查詢優化程式並不能達到理想狀態,所以最好測試一下這兩種方法,看哪種工作得更好。
2.2 UNION 規則
可以看到,UNION
非常容易使用,但在進行組合時需要註意幾條規則。
UNION
必須由兩條或兩條以上的SELECT
語句組成,語句之間用關鍵字UNION
分隔(因此,如果組合四條SELECT
語句,將要使用三個UNION
關鍵字)。UNION
中的每個查詢必須包含相同的列、表達式或聚集函數(不過,各個列不需要以相同的次序列出)。- 列數據類型必須相容:類型不必完全相同,但必須是 DBMS 可以隱含轉換的類型(例如,不同的數值類型或不同的日期類型)。
說明:
UNION
的列名如果結合
UNION
使用的SELECT
語句遇到不同的列名,那麼會返回什麼名字呢?比如說,如果一條語句是SELECT prod_name
,而另一條語句是SELECT productname
,那麼查詢結果返回的是什麼名字呢?答案是它會返回第一個名字,舉的這個例子就會返回
prod_name
,而不管第二個不同的名字。這也意味著你可以對第一個名字使用別名,因而返回一個你想要的名字。這種行為帶來一個有意思的副作用。由於只使用第一個名字,那麼想要排序也只能用這個名字。
拿我們的例子來說,可以用
ORDER BY prod_name
對結果排序,如果寫成ORDER BY productname
就會出錯,因為查詢結果里沒有叫作productname
的列。
如果遵守了這些基本規則或限制,則可以將 UNION
用於任何數據檢索操作。
2.3 包含或取消重覆的行
回到 2.1 節,我們看看所用的 SELECT
語句。
註意到在分別執行語句時,第一條 SELECT
語句返回 3 行,第二條 SELECT
語句返回 2 行。而在用 UNION
組合兩條 SELECT
語句後,只返回 4 行而不是 5 行。
UNION
從查詢結果集中自動去除了重覆的行;換句話說,它的行為與一條 SELECT
語句中使用多個 WHERE
子句條件一樣。
因為 Indiana
州有一個 Fun4All
單位,所以兩條 SELECT
語句都返回該行。使用 UNION
時,重覆的行會被自動取消。
這是 UNION
的預設行為,如果願意也可以改變它。事實上,如果想返回所有的匹配行,可使用 UNION ALL
而不是 UNION
。
請看下麵的例子:
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION ALL
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
輸出:
cust_name cust_contact cust_email
----------- ------------- ------------
Village Toys John Smith [email protected]
Fun4All Jim Jones [email protected]
The Toy Store Kim Howard NULL
Fun4All Jim Jones [email protected]
Fun4All Denise L. Stephens [email protected]
使用 UNION ALL
,DBMS 不取消重覆的行。因此,這裡返回 5 行,其中有一行出現兩次。
提示:
UNION
與WHERE
本文一開始我們說過,
UNION
幾乎總是完成與多個WHERE
條件相同的工作。
UNION ALL
為UNION
的一種形式,它完成WHERE
子句完成不了的工作。如果確實需要每個條件的匹配行全部出現(包括重覆行),就必須使用
UNION ALL
,而不是WHERE
。
2.4 對組合查詢結果排序
SELECT
語句的輸出用 ORDER BY
子句排序。
在用 UNION
組合查詢時,只能使用一條 ORDER BY
子句,它必須位於最後一條 SELECT
語句之後。
對於結果集,不存在用一種方式排序一部分,而又用另一種方式排序另一部分的情況,因此不允許使用多條 ORDER BY
子句。
下麵的例子對前面 UNION
返回的結果進行排序:
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;
輸出:
cust_name cust_contact cust_email
----------- ------------- -------------
Fun4All Denise L. Stephens [email protected]
Fun4All Jim Jones [email protected]
The Toy Store Kim Howard NULL
Village Toys John Smith [email protected]
這條 UNION
在最後一條 SELECT
語句後使用了 ORDER BY
子句。
雖然 ORDER BY
子句似乎只是最後一條 SELECT
語句的組成部分,但實際上 DBMS 將用它來排序所有 SELECT
語句返回的所有結果。
說明:其他類型的
UNION
某些 DBMS 還支持另外兩種
UNION
:EXCEPT
(有時稱為MINUS
)可用來檢索只在第一個表中存在而在第二個表中不存在的行;而
INTERSECT
可用來檢索兩個表中都存在的行。實際上,這些UNION
很少使用,因為相同的結果可利用聯結得到。
提示:操作多個表
為了簡單,本文中的例子都是使用
UNION
來組合針對同一表的多個查詢。實際上,
UNION
在需要組合多個表的數據時也很有用,即使是有不匹配列名的表,在這種情況下,可以將UNION
與別名組合,檢索一個結果集。
三、小結
本文介紹瞭如何用 UNION
操作符來組合 SELECT
語句。利用 UNION
,可以把多條查詢的結果作為一條組合查詢返回,不管結果中有無重覆。
使用 UNION
可極大地簡化複雜的 WHERE
子句,簡化從多個表中檢索數據的工作。
原文鏈接:https://www.developerastrid.com/sql/sql-union/
(完)