1. 程式人生 > >sql GROUP BY子句使用例項

sql GROUP BY子句使用例項

GROUP BY子句
GROUP BY子句可以將表的行劃分為不同的組。分別總結每個組,這樣就可以控制想要看見的詳細資訊的級別。
語法:
[ GROUP BY [ ALL ] group_by_expression[ ,...n ]
[ WITH { CUBE | ROLLUP }  ]  ]
引數說明:
   ALL:包含所有組和結果集,甚至包含那些任何行都不滿足
WHERE子句指定的搜尋條件的組和結果集。如果指定了ALL,將對組中不滿足搜尋條件的彙總列返回空值。不能用CUBE或ROLLUP運算子指定ALL。如果訪問遠端表的查詢中有WHERE子句,則不支援GROUP BY ALL操作。
   group_by_expression:對其執行分組的表示式。

group_by_expression也稱為分組列。group_by_expression可以是列或引用列的非聚合表示式。在選擇列表內定義的列的別名不能用於指定分組列。對於不包含CUBE或ROLLUP的GROUP BY子句,group_by_expression的項數受查詢所涉及的GROUP BY列的大小、聚合列和聚合值的限制。該限制從8060位元組的限制開始,對儲存中間查詢結果所需的中間級工作表有8060位元組的限制。如果指定了CUBE或ROLLUP,則最多隻能有10個分組表示式。
   CUBE:指定在結果集內不僅包含由
GROUP BY提供的正常行,還包含彙總行。在結果集內返回每個可能的組和子組組合的GROUP BY彙總行。GROUP BY彙總行在結果中顯示為NULL,但可用來表示所有值。使用GROUPING函式確定結果集內的空值是否是GROUP BY彙總值。結果集內的彙總行數取決於GROUP BY子句內包含的列數。GROUP BY子句中的每個運算元(列)繫結在分組NULL下,並且分組適用於所有其他運算元(列)。由於CUBE返回每個可能的組和子組組合,因此,不論指定分組列所使用的是什麼順序,行數都相同。
   ROLLUP:指定在結果集內不僅包含由
GROUP BY提供的正常行,還包含彙總行。按層次結構順序,從組內的最低級別到最高級別彙總組。組的層次結構取決於指定分組列時所使用的順序。更改分組列的順序會影響在結果集內生成的行數。使用GROUP BY子句的注意事項。(1)在SELECT子句的欄位列表中,除了聚集函式外,其他所出現的欄位一定要在GROUP BY子句中有定義才行。例如“GROUP BY A,B”,那麼“SELECT SUM(A),C”就有問題,因為C不在GROUP BY中,但是SUM(A)是可以的。(2)SELECT子句的欄位列表中不一定要有聚集函式,但至少要用到GROUP BY子句列表中的一個專案。例如“GROUP BY A,B,C”,則“SELECTA”是可以的。(3
)在SQL Server中text、ntext和image資料型別的欄位不能作為GROUP BY子句的分組依據。(4)GROUP BY子句不能使用欄位別名。
1.按單列進行分組

GROUP BY子句可以基於指定某一列的值將資料集合劃分為多個分組,同一組內所有記錄在分組屬性上具有相同值。
示例:把“student”表按照“性別”這個單列進行分組。在查詢分析器中輸入的SQL語句如下:
use student
select  性別

from  student
group  by 性別
實現的過程如圖1所示。

圖1 “Student”表按“性別”分組但仍然要強調SELECT子句必須與GROUP BY後的子句或者是分組函式列相一致。例如,由於下列查詢中“姓名”列既不包含在GROUP BY子句中,也不包含在分組函式中,所以是錯誤的。錯誤的SQL語句如下:
use  student  select  姓名
,性別 from  student  group  by 性別 


例如,在“grade”表中,按“學期”分組查詢。SQL語句如下:
use  studnet  select 學期 from grade  group by 學期
2.按多列進行分組
GROUP BY子句可以基於指定多列的值將資料集合劃分為多個分組。
示例:
在“student”表中,按照“性別”和“年齡”列進行分組。在查詢分析中輸入的SQL語句如下:
use student
select 性別,年齡
from student
group by 性別,年齡
實現的過程如圖2所示。

圖2  把“student”表按多列進行分組
在“student”表中,首先按照“性別”分組,然後再按照“年齡”分組。
再舉一個例子,例如,在“grade”表中,按照“學號”和“課程代號”列進行分組。SQL語句如下:
use student
select 學號,課程代號  from  grade  group by 學號,課程代號
按多列進行分組時有NULL組的是如何處理的。當表按多列進行分組時有NULL組,這時NULL被作為一個特定值處理,就像其他任何值一樣。也就是說,如果在某個分組列中存在兩個NULL,則按它們有相同的值那樣處理,並將它們放在相同的組中。
示例:
在“grade”表中,按“學期”和“課程代號”列進行分組。在查詢分析器中輸入的SQL語句如下:
use  student
select  學期,課程代號
from grade
group by 學期,課程代號
實現的過程如圖3所示。

圖3  “grade”表多列查詢時的NULL組
3.與聚集函式一起使用
GROUP BY子句是經常與聚集函式一起使用。如果SELECT子句中包含聚集函式,則計算每組的彙總值,當用戶指定GROUP BY時,選擇列表中任一非聚集表示式內的所有列都應包含在GROUP BY列表中,或者GROUP BY表示式必須與選擇列表表示式完全匹配。
示例:
在“student”表中,分別求男女生的平均年齡。在查詢分析器中輸入的SQL語句如下:
use student
select 性別,avg(年齡) as 平均年齡
from student
group by 性別
實現的過程如圖4所示。

圖4  求“Student”表中男女生的平均年齡
例如,在“student”表中,分別求有多少個男生和女生。SQL語句如下:
use student
select 性別,count(性別) as 人數  from student group by 性別
說明:關於聚合函式的詳細講解可參閱9.2.1節。
4.與HAVING子句一起使用
HAVING子句對GROUP BY子句選擇出來的結果進行再次篩選,最後輸出符合HAVING子句中條件的記錄。HAVING子句的語法與WHERE子句的語法相類似,惟一不同的是HAVING子句中可以包含聚合函式。
語法:
[HAVING <search_condition>]
引數說明:
<search_condition>:指定組或聚合應滿足的搜尋條件。當HAVING與GROUP BY ALL一起使用時,HAVING 子句替代ALL。
示例:
在“student”表中,按“性別”分組求平均年齡,並且查詢其平均年齡大於21的學生資訊。在查詢分析器中輸入的SQL語句如下:

use student
select  avg(年齡), 性別
from student
group  by 性別
having avg(年齡)>21
實現的過程如圖5所示。

圖5  男女生中平均年齡大於21的學生資訊
示例:
在“grade”表中,按“學期”分組求平均成績,並且查詢“平均成績”大於93的課程資訊。在查詢分析器中輸入的SQL語句如下:
use    student
select 學期,avg(課程成績) as 平均成績
from   grade
group  by 學期
having avg(課程成績)>93
實現的過程如圖6所示。

圖6  每個學期平均成績大於93的課程資訊
說明:HAVING查詢條件是在進行分組操作之後才應用的;在HAVING子句中不能使用text、image和ntext 資料型別。
5.對統計結果進行排序
統計結果並不能保證結果集內記錄按一定順序排列,如果使用ORDER BY子句,就可以使結果集中的結果按一定的順序(升序、降序)排序。
示例:
在“student”表中,按“性別”和“年齡”列分組,並按“年齡”列降序排序。在查詢分析器中輸入的SQL語句如下:
use    student
select 性別,年齡
from  student
group  by 性別,年齡
order by 年齡 desc
實現的過程如圖7所示。

圖7  對“student”按“年齡”統計並排序
例如,在“grade”表中,按“學號”分組,並按課程的“平均成績”升序排序。SQL語句如下:
use student
select 學號,avg(課程成績) as 平均成績  from grade  group by 學號  order by 平均成績