MySQL必知必會十七:組合查詢

17.1 組合查詢

MySQL允許執行多個查詢(多條SELECT語句),並將結果作爲單個查詢結果集返回。這些組合查詢通常稱爲並( union) 或複合查詢(compound query)。
有兩種基本情況,其中需要使用組合查詢:

  • 在單個查詢中從不同的表返回類似結構的數據;
  • 對單個表執行多個查詢,按單個查詢返回數據。

17.2 創建組合查詢

17.2.1 使用UNION

mysql> SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5 UNION SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1003 | FC      |       2.50 |
|    1002 | FU1     |       3.42 |
|    1003 | SLING   |       4.49 |
|    1003 | TNT1    |       2.50 |
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1002 | OL1     |       8.99 |
+---------+---------+------------+
  • 分析:這條語句由前面的兩條SELECT語句組成,語句中用UNION關鍵字分隔。 UNION指示MySQL執行兩條SELECT語句,並把輸出組合成單個查詢結果集。

作爲參考,這裏給出使用多條WHERE子句而不是使用UNION的相同查詢:

mysql> SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5 OR vend_id IN (1001, 1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1003 | FC      |       2.50 |
|    1002 | FU1     |       3.42 |
|    1002 | OL1     |       8.99 |
|    1003 | SLING   |       4.49 |
|    1003 | TNT1    |       2.50 |
+---------+---------+------------+

在這個簡單的例子中,使用UNION可能比使用WHERE子句更爲複雜。但對於更復雜的過濾條件,或者從多個表(而不是單個表)中檢索數據的情形,使用UNION可能會使處理更簡單。

17.2.2 UNION規則

  • UNION必須由兩條或兩條以上的SELECT語句組成,語句之間用關鍵字UNION分隔(因此,如果組合4條SELECT語句,將要使用3個UNION關鍵字)。
  • UNION中的每個查詢必須包含相同的列、表達式或聚集函數(不過各個列不需要以相同的次序列出)。
  • 列數據類型必須兼容:類型不必完全相同,但必須是DBMS可以隱含地轉換的類型(例如,不同的數值類型或不同的日期類型)。如果遵守了這些基本規則或限制,則可以將並用於任何數據檢索任務。

17.2.3 包含或取消重複的行

UNION從查詢結果集中自動去除了重複的行(換句話說,它的行爲與單條SELECT語句中使用多個WHERE子句條件一樣)。

這是UNION的默認行爲,但是如果需要,可以改變它。事實上,如果想返回所有匹配行,可使用UNION ALL而不是UNION。

mysql> SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5 UNION ALL SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1003 | FC      |       2.50 |
|    1002 | FU1     |       3.42 |
|    1003 | SLING   |       4.49 |
|    1003 | TNT1    |       2.50 |
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1002 | FU1     |       3.42 |
|    1002 | OL1     |       8.99 |
+---------+---------+------------+
  • 分析:使用UNION ALL, MySQL不取消重複的行。因此這裏的例子返回9行,其中有一行出現兩次。

UNION與WHERE UNION幾乎總是完成與多個WHERE條件相同的工作。 UNION ALL爲UNION的一種形式,它完成WHERE子句完成不了的工作。如果確實需要每個條件的匹配行全部出現(包括重複行),則必須使用UNION ALL而不是WHERE

17.2.4 對組合查詢結果排序

SELECT語句的輸出用ORDER BY子句排序。在用UNION組合查詢時,只能使用一條ORDER BY子句,它必須出現在最後一條SELECT語句之後。對於結果集,不存在用一種方式排序一部分,而又用另一種方式排序另一部分的情況,因此不允許使用多條ORDER BY子句。

mysql> SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5 UNION ALL SELECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002) ORDER BY vend_id, prod_price;
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
|    1001 | ANV01   |       5.99 |
|    1001 | ANV02   |       9.99 |
|    1001 | ANV03   |      14.99 |
|    1002 | FU1     |       3.42 |
|    1002 | FU1     |       3.42 |
|    1002 | OL1     |       8.99 |
|    1003 | FC      |       2.50 |
|    1003 | TNT1    |       2.50 |
|    1003 | SLING   |       4.49 |
+---------+---------+------------+
  • 分析:這條UNION在最後一條SELECT語句後使用了ORDER BY子句。雖然ORDER BY子句似乎只是最後一條SELECT語句的組成部分,但實際上MySQL將用它來排序所有SELECT語句返回的所有結果。

組合不同的表 爲使表述比較簡單,本章例子中的組合查詢使用的均是相同的表。但是其中使用UNION的組合查詢可以應用不同的表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章