MySQL必知必會十三:分組數據

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 BYORDER 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 要檢索的行數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章