GROUP BY語句從英文的字面意義上理解就是“根據(jù)(By)一定的規(guī)則進(jìn)行分組(Group)”
作用是通過一定的規(guī)則將一個(gè)數(shù)據(jù)集劃分成若干個(gè)小的區(qū)域禾进,然后針對若干個(gè)小區(qū)域進(jìn)行數(shù)據(jù)處理
在介紹GROUP BY語句之前兜挨,首先需要介紹和它關(guān)系密切的小伙伴——聚合函數(shù)
聚合函數(shù)是對多值數(shù)據(jù)執(zhí)行計(jì)算并返回單值的函數(shù)
以下是常用的聚合函數(shù):
1. AVG——返回平均值,其中空值被忽略
例: select ?dept_no, avg(sal) from table group by dept_no ? //統(tǒng)計(jì)不同部門的平均工資
2.COUNT——返回?cái)?shù)量
例: select count(name) from table ? ?//統(tǒng)計(jì)公司員工總數(shù)
count(字段名)與count(*)的區(qū)別:
如果字段名中包含空值NULL,那么count(字段名)會(huì)忽略該空值,而count(*)不會(huì)忽略,依然將其計(jì)入總數(shù)
例:?
dept_1 dept_2
?A ? ? ? ? ? ? D
?B ? ? ? ? ? null
?C ? ? ? ? ? ?E
由于dept_2 中有 null 值艺挪,用 count(dept_2) 的結(jié)果就是 2,用 count(*) 的結(jié)果就是 3
3. MAX——返回最大值
例: select max(sal) from table ? //查找公司的最高工資
4. MIN——返回最大值
例: select min(sal) from table ? //查找公司的最低工資
5.SUM——返回和
例: select sum(sal) from table ? //統(tǒng)計(jì)公司工資總額
GROUP BY + [分組字段]
其中分組字段可以有多個(gè)兵扬。在執(zhí)行了這個(gè)操作以后麻裳,數(shù)據(jù)集將根據(jù)分組字段的值將一個(gè)數(shù)據(jù)集劃分成各個(gè)不同的小組。
比如有如下數(shù)據(jù)集(Table_Fruitinfo)器钟,其中水果名稱(FruitName)和出產(chǎn)國家(ProductPlace)為聯(lián)合主鍵:
如果我們想知道每個(gè)國家有多少種水果津坑,那么我們可以通過如下SQL語句來完成:
SELECT COUNT(*) AS 水果種類, ProductPlaceAS 出產(chǎn)國
FROM Table_Fruitinfo
GROUP BY ProductPlace
這句SQL語句可以解釋成“我按照出產(chǎn)國家(ProductPlace)將數(shù)據(jù)集進(jìn)行分組,然后分別統(tǒng)計(jì)各個(gè)國家的水果種類數(shù)”傲霸。
注意:如果我們這里水果種類不是用Count(*)疆瑰,而是類似如下寫法的話:
SELECT FruitName, ProductPlace
FROM Table_Fruitinfo
GROUP BY ProductPlace
那么SQL在執(zhí)行此語句的時(shí)候會(huì)報(bào)如下的類似錯(cuò)誤:
選擇列表中的列'Table_Fruitinfo.FruitName'無效,因?yàn)樵摿袥]有包含在聚合函數(shù)或GROUPBY子句中
這就是我們需要注意的一點(diǎn)昙啄,使用GROUP BY語句時(shí)穆役,返回集中的非聚合字段要么包含在Group By語句的后面,作為分組的依據(jù)梳凛;要么就要包含在聚合函數(shù)中耿币。
我們可以將GROUP BY操作想象成如下的一個(gè)過程:
首先通過SELECT語句得到一個(gè)結(jié)果集,然后根據(jù)分組字段韧拒,將具有相同分組字段的記錄歸并成了一條記錄淹接。這時(shí)候那些不作為分組依據(jù)的字段就有可能出現(xiàn)多個(gè)值(非聚合字段),但是一種分組情況只能有一條記錄叛溢,而一個(gè)數(shù)據(jù)格是無法放入多個(gè)數(shù)值的塑悼,所以就需要通過一定的處理(聚合函數(shù))將這些多值的列轉(zhuǎn)化成單值,然后放入對應(yīng)的數(shù)據(jù)格中楷掉。
GROUP BY ALL?+ [分組字段]
在不使用 ALL 關(guān)鍵字的情況下厢蒜,包含 GROUP BY 子句的 SELECT 語句查找的結(jié)果只會(huì)顯示滿足搜索條件的記錄。而使用 ALL 關(guān)鍵字,即使某些記錄不滿足搜索條件郭怪,查詢結(jié)果也將顯示 GROUP BY 子句生成的所有組支示,只是這些不滿足搜索條件的記錄不會(huì)進(jìn)行真正的統(tǒng)計(jì)刊橘,而是用默認(rèn)值0或者NULL來代替聚合函數(shù)的返回值鄙才。說得有點(diǎn)繞,舉個(gè)例子吧促绵。
還是使用之前的水果信息數(shù)據(jù)集
首先我們不使用帶ALL關(guān)鍵字的Group By語句:
SELECT COUNT(*) AS 水果種類, ProductPlace AS 出產(chǎn)國
FROM?Table_Fruitinfo
WHERE (ProductPlace <> 'Japan')
GROUP BY ProductPlace
操作符 <> 表示 ?“不等于”
那么在最后結(jié)果中由于Japan不符合where語句攒庵,所以分組結(jié)果中將不會(huì)出現(xiàn)Japan。
現(xiàn)在我們加入ALL關(guān)鍵字:
SELECT COUNT(*) AS 水果種類, ProductPlace AS 出產(chǎn)國
FROM Table_Fruitinfo
WHERE ( ProductPlace <> 'Japan')
GROUP BY ALL ProductPlace
重新運(yùn)行后败晴,我們可以看到Japan的分組浓冒,但是對應(yīng)的“水果種類”不會(huì)進(jìn)行真正的統(tǒng)計(jì),聚合函數(shù)會(huì)根據(jù)返回值的類型用默認(rèn)值0或者NULL來代替聚合函數(shù)的返回值尖坤。
GROUP BY + [分組字段] WITH CUBE | ROLL UP
GROUP BY ALL語句不能和CUBE / ROLL UP關(guān)鍵字一起使用
CUBE 運(yùn)算符在 SELECT 語句的 GROUP BY 子句中指定稳懒。SELECT語句后跟所查找的維度列和聚合函數(shù)。GROUP BY 后跟所查找的維度列和關(guān)鍵字 WITH CUBE
結(jié)果集包含維度列中各值的所有可能組合(笛卡爾積)慢味,以及與這些維度值組合相匹配的基礎(chǔ)行中的聚合值
例:
以下查詢將返回一個(gè)結(jié)果集场梆,其中包含Item和Color的所有可能組合的Quantity小計(jì):
SELECT Item, Color, SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH CUBE
以下是結(jié)果集:
可以看到,CUBE將維度列Item和Color的所有可能屬性(包括null)進(jìn)行組合纯路,形成了3*3=9條不同的記錄或油,每條記錄都包含著一個(gè)小計(jì)QtySum
但是,CUBE 操作生成空值將會(huì)帶來一個(gè)問題:如何區(qū)分 CUBE 操作生成的 NULL 值和在實(shí)際數(shù)據(jù)中返回的 NULL 值驰唬?
可以使用 GROUPING 函數(shù)解決此問題
如果列值來自真實(shí)數(shù)據(jù)(未知數(shù)據(jù))顶岸,GROUPING 函數(shù)將返回 0;如果列值是由 CUBE 操作生成的 NULL叫编,則返回 1辖佣。
在 CUBE 操作中,生成的 NULL 代表所有值搓逾,所以可以將CUBE操作生成的任一 NULL 替換為字符串 ALL
真實(shí)數(shù)據(jù)中的 NULL 表示數(shù)據(jù)值未知卷谈,所以可以將真實(shí)數(shù)據(jù)中的 NULL替換為字符串 UNKNOWN
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
? ? ? ? ? ? ? ? ? ? ? ? ?ELSE ISNULL(Item, 'UNKNOWN')
? ? ? ? ? ? ? END AS Item,
? ? ? ? ? ? ?CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
? ? ? ? ? ? ? ? ? ? ? ? ELSE ISNULL(Color, 'UNKNOWN')
? ? ? ? ? ? ?END AS Color,
? ? ? ? ? ? ?SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH CUBE
ISNULL:使用指定的替換值替換 NULL。
語法:ISNULL ( check_expression , replacement_value )
如果 check_expression 不為 NULL恃逻,那么返回該表達(dá)式的值雏搂;否則返回 replacement_value。
包含具有多個(gè)維度的 CUBE 的 SELECT 語句可生成大型結(jié)果集寇损,因?yàn)檫@些語句會(huì)為所有維度中各值的所有組合都生成相應(yīng)的行凸郑。這些大型結(jié)果集包含的數(shù)據(jù)可能會(huì)過多而不易于閱讀和理解。此問題的一種解決辦法是將SELECT語句放入視圖(VIEW)中:
數(shù)據(jù)庫中的數(shù)據(jù)都是存儲(chǔ)在表中的矛市,而視圖只是一個(gè)或多個(gè)表依照某個(gè)條件組合而成的結(jié)果集
一般來說可以用UPDATE芙沥,INSERT,DELETE等sql語句修改表中的數(shù)據(jù),而對視圖只能進(jìn)行SELECT操作
CREATE VIEW InvCube AS
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
? ? ? ? ? ? ? ? ? ? ? ? ? ELSE ISNULL(Item, 'UNKNOWN')
? ? ? ? ? ? ? ?END AS Item,
? ? ? ? ? ? ? CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
? ? ? ? ? ? ? ? ? ? ? ? ?ELSE ISNULL(Color, 'UNKNOWN')
? ? ? ? ? ? ? END AS Color,
? ? ? ? ? ? ? SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH CUBE
然后即可用該視圖來僅查詢您感興趣的維度值:
SELECT *
FROM InvCube
WHERE Item = 'Chair'
AND Color = 'ALL'
以下是結(jié)果集:
由于暫時(shí)沒有理解CUBE與ROLLUP有什么實(shí)質(zhì)性區(qū)別而昨,所以先挖個(gè)坑救氯,以后有機(jī)會(huì)再填