9.數據分組 ---SQL
一、創建分組
分組是使用SELECT語句的GROUP BY子句建立的。理解分組的最好辦法是看一個例子:
SELECT vend_id, COUNT(*) AS num_prods FROM Products GROUP BY vend_id;
輸出▼ vend_id num_prods ------- --------- BRS01 3 DLL01 4 FNG01 2
分析▼
上面的SELECT語句指定了兩個列:vend_id包含產品供應商的ID,num_prods為計算字段(用COUNT(*)函數建立)。GROUP BY子句指示
DBMS按vend_id排序並分組數據。這就會對每個vend_id而不是整個表計算num_prods一次。從輸出中可以看到,供應商BRS01有3個產品,供
因為使用了GROUP BY,就不必指定要計算和估值的每個組了。系統會自動完成。GROUP BY子句指示DBMS分組數據,然後對每個組而不是整
個結果集進行聚集。
在使用GROUP BY子句前,需要知道一些重要的規定。
- GROUP BY子句可以包含任意數目的列,因而可以對分組進行嵌套,更細致地進行數據分組。
- 如果在GROUP BY子句中嵌套了分組,數據將在最後指定的分組上進行匯總。換句話說,在建立分組時,指定的所有列都一起計算(所以
- 不能從個別的列取回數據)。
- GROUP BY子句中列出的每一列都必須是檢索列或有效的表達式(但不能是聚集函數)。如果在SELECT中使用表達式,則必須在GROUP
- BY子句中指定相同的表達式。不能使用別名。
- 大多數SQL實現不允許GROUP BY列帶有長度可變的數據類型(如文本或備註型字段)。
- 除聚集計算語句外,SELECT語句中的每一列都必須在GROUP BY子句中給出。
- 如果分組列中包含具有NULL值的行,則NULL將作為一個分組返回。如果列中有多行NULL值,它們將分為一組。
- GROUP BY子句必須出現在WHERE子句之後,ORDER BY子句之前。
提示:ALL子句
Microsoft SQL Server等有些SQL實現在GROUP BY中支持可選的A LL子句。這個子句可用來返回所有分組,即使是沒有匹配行的分組也返回
警告:通過相對位置指定列
有的SQL實現允許根據SELECT列表中的位置指定GROUP BY的列。例如,GROUP BY 2, 1可表示按選擇的第二個列分組,然後再按第一個列
分組。雖然這種速記語法很方便,但並非所有SQL實現都支持,並且使用它容易在編輯SQL語句時出錯。
二、過濾分組
HAVING
SELECT cust_id, COUNT(*) AS orders FROM Orders GROUP BY cust_id HAVING COUNT(*) >= 2;
輸出▼ cust_id orders ---------- ----------- 1000000001 2
分析▼
這條SELECT語句的前三行類似於上面的語句。最後一行增加了HA VING子句,它過濾COUNT(*) >= 2(兩個以上訂單)的那些分組。
可以看到,WHERE子句在這裏不起作用,因為過濾是基於分組聚集值,而不是特定行的值。
說明:HAVING和WHERE的差別
這裏有另一種理解方法,WHERE在數據分組前進行過濾,HA VING在數據分組後進行過濾。這是一個重要的區別,WHERE排除的行不包括
在分組中。這可能會改變計算值,從而影響HA VING子句中基於這些值過濾掉的分組。
說明:使用HAVING和WHERE
HA VING與WHERE非常類似,如果不指定GROUP BY,則大多數DBMS會同等對待它們。不過,你自己要能區分這一點。使用HA VING時應
該結合GROUP BY子句,而WHERE子句用於標準的行級過濾。
三、分組和排序
我們經常發現,用GROUP BY分組的數據確實是以分組順序輸出的。但並不總是這樣,這不是SQL規範
所要求的。此外,即使特定的DBMS總是按給出的GROUP BY子句排序數據,用戶也可能會要求以不同的順序排序。就因為你以某種方式分組
數據(獲得特定的分組聚集值),並不表示你需要以相同的方式排序輸出。應該提供明確的ORDER BY子句,即使其效果等同於GROUP BY子
句。
提示:不要忘記ORDER BY
一般在使用GROUP BY子句時,應該也給出ORDER BY子句。這是保證數據正確排序的唯一方法。千萬不要僅依賴GROUP BY排序數據。
四、ELECT子句順序
9.數據分組 ---SQL