13.1 創建分組
分組是在SELECT
語句的GROUP BY
子句中建立的。理解分組的最好辦法是看一個例子:
mysql> SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
+---------+-----------+
- 分析:上面的
SELECT
語句指定了兩個列,vend_id
包含產品供應商的ID,num_prods
爲計算字段(用COUNT(*)
函數建立)。GROUP BY
子句指示MySQL按vend_id
排序並分組數據。這導致對每個vend_id
而不是整個表計算num_prods
一次。從輸出中可以看到,供應商1001有3個產品,供應商1002有2個產品,供應商1003有7個產品,而供應商1005有2個產品。
因爲使用了GROUP BY
,就不必指定要計算和估值的每個組了。系統會自動完成。 GROUP BY
子句指示MySQL分組數據,然後對每個組而不是整個結果集進行聚集。
13.2 過濾分組
mysql> SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2;
+---------+--------+
| cust_id | orders |
+---------+--------+
| 10001 | 2 |
+---------+--------+
- 分析:這條
SELECT
語句的前3行類似於上面的語句。最後一行增加了HAVING
子句,它過濾COUNT(*) >=2
(兩個以上的訂單)的那些分組。
HAVING和WHERE的差別:這裏有另一種理解方法,WHERE在數據分組前進行過濾, HAVING在數據分組後進行過濾。
列出具有2個(含)以上、價格爲10(含)以上的產品的供應商:
mysql> SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1003 | 4 |
| 1005 | 2 |
+---------+-----------+
- 分析:這條語句中,第一行是使用了聚集函數的基本
SELECT
,它與前面的例子很相像。WHERE
子句過濾所有prod_price
至少爲10的行。然後按vend_id
分組數據,HAVING
子句過濾計數爲2或2以上的分組。如果沒有WHERE
子句,將會多檢索出兩行(供應商1002,銷售的所有產品價格都在10以下;供應商1001,銷售3個產品,但只有一個產品的價格大於等於10):
mysql> SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id HAVING COUNT(*) >= 2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
+---------+-----------+
13.3 分組和排序
不要忘記ORDER BY:一般在使用GROUP BY
子句時,應該也給出ORDER BY
子句。這是保證數據正確排序的唯一方法。千萬不要僅依賴GROUP BY
排序數據
爲說明GROUP BY
和ORDER BY
的使用方法,請看一個例子。下面SELECT
語句類似於前面那些例子。它檢索總計訂單價格大於等於50的訂單的訂單號和總計訂單價格:
mysql> SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50;
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
| 20005 | 149.87 |
| 20006 | 55.00 |
| 20007 | 1000.00 |
| 20008 | 125.00 |
+-----------+------------+
爲按總計訂單價格排序輸出,需要添加ORDER BY子句,如下所示:
mysql> SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50 ORDER BY ordertotal;
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
| 20006 | 55.00 |
| 20008 | 125.00 |
| 20005 | 149.87 |
| 20007 | 1000.00 |
+-----------+------------+
- 分析:在這個例子中,
GROUP BY
子句用來按訂單號(order_num列)分組數據,以便SUM(*)
函數能夠返回總計訂單價格。HAVING
子句過濾數據,使得只返回總計訂單價格大於等於50的訂單。最後, 用ORDER BY
子句排序輸出。
13.4 SELECT子句順序
在SELECT語句中使用時必須遵循的次序,列出迄今爲止所學過的子句。
子 句 | 說 明 | 是否必須使用 |
---|---|---|
SELECT | 要返回的列或表達式 | 是 |
FROM | 從中檢索數據的表 | 僅在從表選擇數據時使用 |
WHERE | 行級過濾 | 否 |
GROUP BY | 分組說明 | 僅在按組計算聚集時使用 |
HAVING | 組級過濾 | 否 |
ORDER BY | 輸出排序順序 | 否 |
LIMIT | 要檢索的行數 | 否 |