今天看到了這個(gè)文章感覺(jué)內(nèi)容挺多的,就是比較亂,實(shí)在不好整理,腳本之家小編就簡(jiǎn)單整理了一下,希望大家能湊合看吧
分組后分組合計(jì)以及總計(jì)SQL語(yǔ)句
1)想一次性得到分組合計(jì)以及總計(jì),sql:
SELECT 分組字段 FROM 表
GROUP BY 分組字段
compute sum(COUNT(*))
2)分組合計(jì)1:
SELECT COUNT(*) FROM (SELECT 分組字段 FROM 表 GROUP BY 分組字段 )別名
3)分組合計(jì)2:
SELECT COUNT(*) FROM (SELECT distinct 分組字段 FROM 表)別名
4)統(tǒng)計(jì)分組后的種類(lèi)數(shù):
例子1:分組合計(jì)
SELECT JSSKQK_JGH FROM SJ_JSSKQK WHERE JSSKQK_JGH IN (SELECT JSJBXX_JGH FROM SJ_JSJBXX WHERE JSJBXX_JSLXM1=1) GROUP BY JSSKQK_JGH HAVING ((SUM(JSSKQK_SSKCXS1) /40)>5)
上面的語(yǔ)句已經(jīng)可以滿足要求分組了.假設(shè)執(zhí)行后有3條記錄,怎么才能把這個(gè)COUNT值求出?
select count(*) from ( SELECT JSSKQK_JGH FROM SJ_JSSKQK WHERE JSSKQK_JGH IN (SELECT JSJBXX_JGH FROM SJ_JSJBXX WHERE JSJBXX_JSLXM1=1) GROUP BY JSSKQK_JGH HAVING ((SUM(JSSKQK_SSKCXS1) /40)>5) ) t
例子2:[PL/SQL] 如何得到分組后,組中最大日期的紀(jì)錄
TABLE:A
A B C D
1 2001/01/01 1 1
1 2001/12/12 2 2
3 2002/01/01 3 3
3 2003/12/12 4 4
按列A分組,請(qǐng)問(wèn)如何得到每組中時(shí)間最大的數(shù)據(jù)?
1 2001/12/12 2 2
3 2003/12/12 4 4
我的笨方法:
SELECT * FROM A WHERE (A,B) IN( SELECT A,MAX(B) FROM A GROUP BY A )
有更好的方法嗎?
1,select * from a out
where b = (select max(b) from a in
where in.a = out.a)
2,Select * from
(select a, row_number() over (partition by a
order by b desc) rn
from a)
where rn=1
3,Select a, b,c,d from
(select a, b,c,d,row_number() over (partition by a
order by b desc) rn
from a)
where rn=1
4,select A,B,C,D from test
where rowid in
(
select rd from
(
select rowid rd ,rank() over(partion A order by B desc)rk from test
) where rk=1
)
)
例子3:SQL語(yǔ)句分組獲取記錄的第一條數(shù)據(jù)的方法
使用Northwind 數(shù)據(jù)庫(kù)
首先查詢Employees表
查詢結(jié)果:
city列里面只有5個(gè)城市
使用ROW_NUMBER() OVER(PARTITION BY COL1 ORDER BY COL2) 先進(jìn)行分組 注:根據(jù)COL1分組,在分組內(nèi)部根據(jù) COL2排序,而此函數(shù)計(jì)算的值就表示每組內(nèi)部排序后的順序編號(hào)(組內(nèi)連續(xù)的唯一的).
sql語(yǔ)句為:
select EmployeeID,LastName,FirstName,Title,TitleOfCourtesy,City,ROW_NUMBER() over(partition by City order by EmployeeID) as new_index
from Employees
執(zhí)行結(jié)果圖:
可以看到是按照City分組,EmployeeID排序。
select出分組中的第一條記錄
執(zhí)行語(yǔ)句:
select * from
(select EmployeeID,LastName,FirstName,Title,TitleOfCourtesy,City,ROW_NUMBER() over(partition by City order by EmployeeID) as new_index
from Employees) a where a.new_index=1
執(zhí)行結(jié)果圖:
例子4:sql 獲取分組結(jié)果后,如何每一組的第一條記錄
Eric red 20
eric blue 30
andy red 10
andy blue 5
例如,只獲取黑體的記錄。
1,declare @fTable table (fName varchar(10), fColor varchar(10), fOrder int)
insert into @fTable values('Eric', 'red', 20)
insert into @fTable values('eric', 'blue', 30)
insert into @fTable values('andy', 'red', 10)
insert into @fTable values('andy', 'blue', 5)
-- 只獲取紅色
select * from @fTable where fColor = 'red'
-- 每個(gè) fColor 取一條記錄(按 fOrder 正序)
select * from @fTable A where fName = (select top 1 fName from @fTable where fColor = A.fColor order by fOrder )
-- 每個(gè) fColor 取一條記錄(按 fOrder 反序)
select * from @fTable A where fName = (select top 1 fName from @fTable where fColor = A.fColor order by fOrder desc)
2,SQL2005以上版本
select * from (select *,row=row_number()over(partition by Color order by Color) from table1)t where row=1 and color='xx'--加上條件
SQL2000用 top 1
例子5:一條SQL語(yǔ)句搞定分組并且每組限定記錄集的數(shù)量
如果我想得到這樣一個(gè)結(jié)果集:分組,并且每組限定記錄集的數(shù)量,用一條SQL語(yǔ)句能辦到嗎?
比如說(shuō),我想找出學(xué)生期末考試中,每科的前3名,只用一條SQL語(yǔ)句,該怎么寫(xiě)?
表[TScore]的結(jié)構(gòu)
code 學(xué)號(hào) char
subject 科目 int
score 成績(jī) int
可以這樣寫(xiě):
SELECT [code]
,[subject]
,[score]
FROM (
SELECT *
,RANK() OVER(PARTITION BY subject ORDER BY score DESC) AS Row
FROM TScore
) AS a
WHERE Row = 3 ;
例子6:SQL獲取每個(gè)分組的第一條記錄
SQL查詢以下偽數(shù)據(jù)獲取粗體字行的記錄
ID,Name,ItemID,Price,CreatedOn
1 a 1 10.00 xxx1
2 a 1 12.00 xxx2
3 b 1 9.00 xxx1
4 b 1 11.50 xxx2
5 c 1 20.00 xxx1
6 a 2 21.00 xxx1
7 a 2 23.00 xxx2
8 b 2 35.00 xxx1
9 c 2 31.00 xxx1
10 c 2 30.50 xxx2
獲取每個(gè)分組中的第一條記錄,當(dāng)ItemID有多條記錄時(shí),選取Price最高的
--sql2000
select *
from tbname k
where not exists(select * from tbname where
name=k.name and ITemID=K.ITemID and k.priceprice
)
--sql2005
select ID,Name,ItemID,Price,CreatedOnfrom (select *,rn=ROW_NUMBER()over(PARTITION by name,ITemID order by price desc) from tb ) kwhere k.rn=1
例子7:分組后取第一條記錄的SQL語(yǔ)句
分享
有如下表結(jié)構(gòu):
字段 A, B, C
值為 a1, b1, c1
a2, b2, c2
a2, b3, c3
a3, b4, c4
a3, b5, c5
想要得到的結(jié)果集以A字段為分組條件,并取出每一個(gè)分組中的第一條記錄,如下:
A, B, C
值為 a1, b1, c1 --a1分組的第一條記錄。
a2, b2, c2 --a2分組的第一條記錄。
a3, b4, c4 --a3分組的第一條記錄。
select * from 表 tem where c=(select top 1 c from 表 where a=tem.a)
現(xiàn)有數(shù)據(jù)表call如下:
zj th bj
------------- -------- -------------
03106666666 00001 03101111111
13711111111 00001 031122222222
03108898888 950000
031177778777 950000
031155955555 00001 031187888876
注:th如為950000,則bj為空,th如為00001,則bj不是空。
1、bj分組
select substr(bj,1,4) as 區(qū)號(hào),count(*) as 呼叫總量 from call
group by substr(bj,1,4);
執(zhí)行結(jié)果
區(qū)號(hào) 呼叫總量
------------ --------------
0310 1
0311 2
2
2、zj分組,條件是th為950000的記錄
select substr(zj,1,4) as 區(qū)號(hào),count(*) as 呼叫總量 from call
where th=950000
group by substr(zj,1,4);
執(zhí)行結(jié)果:
區(qū)號(hào) 呼叫總量
------------ --------------
0310 1
0311 1
能否有一個(gè)語(yǔ)句就能實(shí)現(xiàn)如下結(jié)果:
區(qū)號(hào) 呼叫總量
------------ --------------
0310 2
0311 3
注:想要得到結(jié)果是1對(duì)應(yīng)的行加2對(duì)應(yīng)的行。
union起來(lái)再求和
select 區(qū)號(hào),sum(呼叫總量) from
(select substr(bj,1,4) as 區(qū)號(hào),count(*) as 呼叫總量 from call
group by substr(bj,1,4))
union all
(select substr(zj,1,4) as 區(qū)號(hào),count(*) as 呼叫總量 from call
where th=950000
group by substr(zj,1,4))
group by 區(qū)號(hào);
這個(gè)應(yīng)該在Oracle中運(yùn)行
select
decode(th,'950000',substr(zj,1,4),substr(bj,1,4)) as 區(qū)號(hào),
count(*) as 呼叫總量
from
call
group by
decode(th'950000',substr(zj,1,4),substr(bj,1,4))
decode(條件,值1,翻譯值1,值2,翻譯值2,...值n,翻譯值n,缺省值)
該函數(shù)的含義如下:
IF 條件=值1 THEN
RETURN(翻譯值1)
ELSIF 條件=值2 THEN
RETURN(翻譯值2)
......
ELSIF 條件=值n THEN
RETURN(翻譯值n)
ELSE
RETURN(缺省值)
END IF
例子8:在SQL Server2005/2008中對(duì)記錄進(jìn)行分組,并獲得每組前N條記錄
假設(shè)有一個(gè)表,SQL語(yǔ)句如下:
CREATE TABLE [dbo].[scan](
[km] [int] NULL,
[kh] [int] NULL,
[cj] [int] NULL
) ON [PRIMARY]
其中km為科目號(hào)、kh為考生號(hào)、cj為成績(jī),現(xiàn)對(duì)km和kh進(jìn)行分組,并獲得每組前2條記錄(按cj從高到低排序)。基本思想是為每組加一個(gè)序號(hào)列,再用where取序號(hào)小于等于2的。SQL語(yǔ)句如下:
select * from
(
select a.km,a.kh,cj,row_number() over(partition by a.km order by a.km,a.cj desc) n
from
(select km,kh,SUM(cj) cj from scan group by km,kh) a
) b where n=2 order by km, cj desc
最后得到的結(jié)果集如下圖所示。
例子9:如何實(shí)現(xiàn)分組Group取前N條記錄的sql語(yǔ)句
在表A中根據(jù)字段B分組、根據(jù)字段C排序并查詢出每組中的前三條記錄,查詢結(jié)果要求包含所有字段,請(qǐng)問(wèn)sql語(yǔ)句該怎么寫(xiě)?下面的sql語(yǔ)句雖然可以實(shí)現(xiàn),但由于數(shù)據(jù)量比較大,耗費(fèi)時(shí)間太長(zhǎng),有沒(méi)有不通過(guò)表聯(lián)接而直接分組取記錄的方法呢?多謝!
select *
from 表A as t1
where 主鍵 in(
select top 3 主鍵
from 表A as t2
where t1.B=t2.B
order by t2.C)
注釋 (隱藏注釋)
答案1
作者:鄒建
select id=identity(int,1,1),b, 主鍵 into # from 表A order by B,C
select a.*
from 表A a, # b,(select id1=min(id),id2=min(id)+2 from # group by b)c
where a.主鍵=b.主鍵
and b.id between c.id1 and c.id2
drop table #
答案2
作者:aierong
求每組前2名,你有幾種方法?(MS SQL2000)
create table abc(
i nvarchar(10),
ii int,
iii int,
iiii int,
price money)
Go
insert into abc
select 'b',1,2,1,11
union all
select 'b',211,2,1,211
union all
select 'a',21,2,1,311
union all
select 'd',41,42,1,411
union all
select 'd',41,42,1,511
union all
select 'd',41,42,1,611
union all
select 'e',1,2,1,11
union all
select 'e',71,2,1,31
union all
select 'e',61,2,1,911
union all
select 'e',771,2,1,1
go
要求的結(jié)果是:
以i分組,求每組price最大的前2條記錄
i ii iii iiii price
---------- ----------- ----------- ----------- ---------------------
a 21 2 1 311.0000
b 1 2 1 11.0000
b 211 2 1 211.0000
d 41 42 1 511.0000
d 41 42 1 611.0000
e 71 2 1 31.0000
e 61 2 1 911.0000
1.
select *
from abc a
where (
select counthttp://dev1.haocang.com:8080/kb/images/icons/emoticons/star_yellow.gif from abc b
where a.i=b.i and b.price>a.price)2
order by i,price
連接查詢,判斷數(shù)量
2.
select i,ii,iii,iiii,price
from (
select (select isnull(sum(1),0)+1 from abc b where a.i=b.i and a.priceb.price) ids,*
from abc a) tem
where ids3
order by i,price
生產(chǎn)一個(gè)內(nèi)部表,給內(nèi)部表tem中的每一組排序,并把排序號(hào)放入新列ids中
3.
declare @looptime int
declare @count int
declare @i nvarchar(10)
/定義表變量@abc,和表ABC中的所有列類(lèi)型相同/
declare @abc table(
i nvarchar(10),
ii int,
iii int,
iiii int,
price money)
declare @tem table(
ids int identity,
class nvarchar(10))
/把表ABC中的所有組全部查詢出來(lái),暫時(shí)存在表變量@tem中/
insert into @tem(class)
select i
from abc
group by i
/求出表變量@tem中行數(shù)量/
select @count=@@rowcount
/循環(huán)變量@looptime賦初值=1/
select @looptime=1
while(@looptime=@count)
begin
/將每組名賦值到變量@i/
select @i=class
from @tem
where ids=@looptime
/將每組前2名插入到表變量@abc中/
insert into @abc
select top 2 *
from abc
where i=@i
order by price desc
/循環(huán)變量@looptime累加1/
select @looptime=@looptime+1
end
/顯示結(jié)果/
select *
from @abc
order by i,price
4.
用游標(biāo)來(lái)處理
方法和我的第3種方法類(lèi)似,大家可以自己試試
我共寫(xiě)了4種,不知道大家還有什么其他好方法,可以交流,謝謝。
今天用到了,利用此方法可以解決一個(gè)刪除重復(fù)記錄的問(wèn)題
當(dāng)然表必須帶有唯一索引,仔細(xì)看以下代碼
Delete From dbo.TB_WorkflowTask a
WHERE ItemID Not in( select top 1 ItemID from TB_WorkflowTask where TaskName=a.TaskName And EmpID = a.EmpID And BillTypeID =a.BillTypeID And BillID = a.BillID And Status =a.Status AND WFStatus =a.WFStatus )
注意:只能用 In 或 Not in ,不能用Exists 或 Not Exists ,至于為什么,大家思考一下?
例子10:如何取得分組后最后一條記錄的值?
還是很混亂,再排一下:
重新整理一下格式:
現(xiàn)有一表 Log: Day In Out Current
2012.4.5 10 0 10
2012.4.5 0 5 5
2012.4.6 30 20 15
2012.4.6 0 3 12
………………………………………………
希望顯示為
、
2012.4.5 10 5 5
2012.4.6 30 23 12
SQL code
with tb as(
select [day],sum([in]) as [in],sum(out) as out,sum([in])-sum(out) as [current],rank() over( order by [day]) as row from [log] group by [day]
)
select [day],[in],out,(select sum([current]) from tb b where b.row=a.row)[current] from tb a
SQL code
2012.4.5 10 5 5
2012.4.6 30 23 12
SQL code
--> 測(cè)試數(shù)據(jù):[Log]
if object_id('[Log]') is not null drop table [Log]
create table [Log]([Day] date,[In] int,[Out] int,[Current] int)
insert [Log]
select '2012.4.5',10,0,10 union all
select '2012.4.5',0,5,5 union all
select '2012.4.6',30,20,15 union all
select '2012.4.6',0,3,12
select
[Day],sum([In]) [In],sum([Out]) [Out],min([Current]) as [Current]
from [Log] group by [Day]
/*
Day In Out Current
2012-04-05 10 5 5
2012-04-06 30 23 12
*/
例子11:sql分組后二次匯總
https://www.jb51.net/article/106074.htm
例子12:sql的分類(lèi)與分組統(tǒng)計(jì)
您需要了解如何使用某些SQL子句和運(yùn)算符來(lái)安排SQL數(shù)據(jù),從而對(duì)它進(jìn)行高效分析。下面這些建議告訴您如何建立語(yǔ)句,獲得您希望的結(jié)果。
以 有意義的方式安排數(shù)據(jù)可能是一種挑戰(zhàn)。有時(shí)您只需進(jìn)行簡(jiǎn)單分類(lèi)。通常您必須進(jìn)行更多處理——進(jìn)行分組以利于分析與總計(jì)??上驳氖?,SQL提供了大量用于分 類(lèi)、分組和總計(jì)的子句及運(yùn)算符。下面的建議將有助于您了解何時(shí)進(jìn)行分類(lèi)、何時(shí)分組、何時(shí)及如何進(jìn)行總計(jì)。欲了解每個(gè)子句和運(yùn)算符的詳細(xì)信息,請(qǐng)查看
。
#1:分類(lèi)排序
通常,我們確實(shí)需要對(duì)所有數(shù)據(jù)進(jìn)行排序。SQL的ORDER BY子句將數(shù)據(jù)按字母或數(shù)字順序進(jìn)行排列。因此,同類(lèi)數(shù)據(jù)明顯分類(lèi)到各個(gè)組中。然而,這些組只是分類(lèi)的結(jié)果,它們并不是真正的組。ORDER BY顯示每一個(gè)記錄,而一個(gè)組可能代表多個(gè)記錄。
#2:減少組中的相似數(shù)據(jù)
分類(lèi)與分組的最大不同在于:分類(lèi)數(shù)據(jù)顯示(任何限定標(biāo)準(zhǔn)內(nèi)的)所有記錄,而分組數(shù)據(jù)不顯示這些記錄。GROUP BY子句減少一個(gè)記錄中的相似數(shù)據(jù)。例如,GROUP BY能夠從重復(fù)那些值的源文件中返回一個(gè)唯一的郵政編碼列表:
SELECT ZIP
FROM Customers
GROUP BY ZIP
僅包括那些在GROUP BY和SELECT列列表中字義組的列。換句話說(shuō),SELECT列表必須與GROUP列表相匹配。只有一種情況例外:SELECT列表能夠包含聚合函數(shù)。(而GROUP BY不支持聚合函數(shù)。)
記住,GROUP BY不會(huì)對(duì)作為結(jié)果產(chǎn)生的組分類(lèi)。要對(duì)組按字母或數(shù)字順序排序,增加一個(gè)ORDER BY子句(#1)。另外,在GROUP BY子句中您不能引用一個(gè)有別名的域。組列必須在根本數(shù)據(jù)中,但它們不必出現(xiàn)在結(jié)果中。
#3:分組前限定數(shù)據(jù)
您可以增加一個(gè)WHERE子句限定由GROUP BY分組的數(shù)據(jù)。例如,下面的語(yǔ)句僅返回肯塔基地區(qū)顧客的郵政編碼列表。
SELECT ZIP
FROM Customers
WHERE State = 'KY'
GROUP BY ZIP
在GROUP BY子句求數(shù)據(jù)的值之前,WHERE對(duì)數(shù)據(jù)進(jìn)行過(guò)濾,記住這一點(diǎn)很重要。
和GROUP BY一樣,WHERE不支持聚合函數(shù)。
#4:返回所有組
當(dāng) 您用WHERE過(guò)濾數(shù)據(jù)時(shí),得到的組只顯示那些您指定的記錄。符合組定義但不滿足子句條件的數(shù)據(jù)將不會(huì)出現(xiàn)在組中。不管WHERE條件如何,如果您想包括 所有數(shù)據(jù),增加一個(gè)ALL子句。例如,在前面的語(yǔ)句中增加一個(gè)ALL子句會(huì)返回所有郵政編碼組,而不僅僅是肯塔基地區(qū)的組。
SELECT ZIP
FROM Customers
WHERE State = 'KY'
GROUP BY ALL ZIP
照這個(gè)樣子,這兩個(gè)子句會(huì)造成沖突,您可能不會(huì)以這種方式使用ALL子句。當(dāng)您用聚合求一個(gè)列的值時(shí),應(yīng)用ALL子句很方便。例如,下面的語(yǔ)句計(jì)算每個(gè)肯塔基郵政編碼的顧客數(shù)目,同時(shí)顯示其它郵政編碼值。
SELECT ZIP, Count(ZIP) AS KYCustomersByZIP
FROM Customers
WHERE State = 'KY'
GROUP BY ALL ZIP
得到的組由根本數(shù)據(jù)中的所有郵政編碼值構(gòu)成。但是,聚合列(KYCustomerByZIP)顯示為0,因?yàn)槌纤]政編碼組外沒(méi)有別的組。
遠(yuǎn)程查詢不支持GROUP BY ALL。
#5:分組后限定數(shù)據(jù)
WHERE 子句(#3)在GROUP BY子句之前求數(shù)據(jù)的值。當(dāng)您希望在分組以后限定數(shù)據(jù)時(shí),使用HAVING。通常,不管您使用WHERE還是HAVING,得到的結(jié)果相同。但要記住,這 兩個(gè)子句不能互換,這點(diǎn)很重要。如果您存在疑問(wèn),這里有一條應(yīng)用指南:過(guò)濾記錄時(shí)使用WHERE;過(guò)濾組時(shí)使用HAVING。
一般,您會(huì)用HAVING,利用聚合來(lái)求一個(gè)組的值。例如,下面的語(yǔ)句返回一個(gè)郵政編碼列表,但這個(gè)表內(nèi)可能不包含根本數(shù)據(jù)源中的每個(gè)郵政編碼:
SELECT ZIP, Count(ZIP) AS CustomersByZIP
FROM Customers
GROUP BY ZIP
HAVING Count(ZIP) = 1
僅僅那些只有一名顧客的組出現(xiàn)在結(jié)果中。
#6:詳細(xì)了解WHERE和HAVING
如果您仍然對(duì)WHERE和HAVING的用法感到迷惑,應(yīng)用下面的指導(dǎo)方法:
WHERE出現(xiàn)在GROUP BY之前;SQL在它分組記錄前求WHERE子句的值。
HAVING出現(xiàn)在GROUP BY之后;SQL在它分組記錄后求HAVING子句的值。
#7:用聚合總計(jì)分組值
分組數(shù)據(jù)有助于對(duì)數(shù)據(jù)進(jìn)行分析,但有時(shí)您還需要組本身以外的其它信息。您可以增加一個(gè)聚合函數(shù)來(lái)總計(jì)分組數(shù)據(jù)。例如,下面的語(yǔ)句為每次排序顯示一個(gè)小計(jì):
SELECT OrderID, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY OrderID
與其它的組一樣,SELECT和GROUP BY列表必須相匹配。在SELECT子句中包含一個(gè)聚合是這一規(guī)則的唯一例外。
#8:總計(jì)聚合
您可以通過(guò)顯示每個(gè)組的小計(jì)進(jìn)一步總計(jì)數(shù)據(jù)。SQL的ROLLUP運(yùn)算符為每個(gè)組顯示一個(gè)額外的記錄,一個(gè)小計(jì)。那個(gè)記錄是用聚合函數(shù)在每個(gè)組中求所有記錄的值的結(jié)果。下面的語(yǔ)句為每個(gè)組合計(jì)OrderTotal列。
SELECT Customer, OrderNumber, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY Customer, OrderNumber
WITH ROLLUP
一個(gè)包含20和25這兩個(gè)OrderTotal值的組的ROLLUP行將顯示OrderTotal值45。ROLLUP結(jié)果的第一個(gè)值是唯一的,因?yàn)樗笏薪M記錄的值。那個(gè)值是整個(gè)記錄集的總和。
ROLLUP不支持聚合函數(shù)中的DISTINCT或GROUP BY ALL子句。
#9:總計(jì)每一列
CUBE運(yùn)算符比ROLLUP更進(jìn)一步,它返回每個(gè)組中每個(gè)值的總數(shù)。得到的結(jié)果與ROLLUP相似,但CUBE包括組中每一列的一個(gè)額外記錄。下面的語(yǔ)句顯示每個(gè)組的小計(jì)和每名顧客的一個(gè)額外總數(shù)。
SELECT Customer, OrderNumber, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY Customer, OrderNumber
WITH CUBE
用CUBE得到的總計(jì)最為復(fù)雜。不僅完成聚合與ROLLUP的工作,而且還求定義組的其它列的值。也就是說(shuō),CUBE總計(jì)每一個(gè)可能的列組合。
CUBE不支持GROUP BY ALL。
#10:給總計(jì)排序
當(dāng)CUBE的結(jié)果雜亂無(wú)章時(shí)(一般都是這樣),可以增加一個(gè)GROUPING函數(shù),如下所示:
SELECT GROUPING(Customer), OrderNumber, Sum(Cost * Quantity) AS OrderTotal
FROM Orders
GROUP BY Customer, OrderNumber
WITH CUBE
其結(jié)果包括每一行的兩個(gè)額外的值。
值1表明左邊的值是一個(gè)總計(jì)值——ROLLUP或CUBE的運(yùn)算符的結(jié)果。
值0表明左邊的值是一個(gè)原始GROUP BY子句產(chǎn)生的詳細(xì)記錄。
在分組查詢中還可以配合使用HAVING子句,定義查詢條件。
使用group by進(jìn)行分組查詢
在使用group by關(guān)鍵字時(shí),在select列表中可以指定的項(xiàng)目是有限制的,select語(yǔ)句中僅許以下幾項(xiàng):
〉被分組的列
〉為每個(gè)分組返回一個(gè)值得表達(dá)式,例如用一個(gè)列名作為參數(shù)的聚合函數(shù)
group by 有一個(gè)原則,就是 select 后面的所有列中,沒(méi)有使用聚合函數(shù)的列,必須出現(xiàn)在 group by 后面(重要)
group by實(shí)例
實(shí)例一
數(shù)據(jù)表:
姓名 科目 分?jǐn)?shù)
張三 語(yǔ)文 80
張三 數(shù)學(xué) 98
張三 英語(yǔ) 65
李四 語(yǔ)文 70
李四 數(shù)學(xué) 80
李四 英語(yǔ) 90
期望查詢結(jié)果:
姓名 語(yǔ)文 數(shù)學(xué) 英語(yǔ)
張三 80 98 65
李四 70 80 90
代碼
create table testScore
(
tid int primary key identity(1,1),
tname varchar(30) null,
ttype varchar(10) null,
tscor int null
)
go
---插入數(shù)據(jù)
insert into testScore values ('張三','語(yǔ)文',80)
insert into testScore values ('張三','數(shù)學(xué)',98)
insert into testScore values ('張三','英語(yǔ)',65)
insert into testScore values ('李四','語(yǔ)文',70)
insert into testScore values ('李四','數(shù)學(xué)',80)
insert into testScore values ('李四','英語(yǔ)',90)
select tname as '姓名' ,
max(case ttype when '語(yǔ)文' then tscor else 0 end) '語(yǔ)文',
max(case ttype when '數(shù)學(xué)' then tscor else 0 end) '數(shù)學(xué)',
max(case ttype when '英語(yǔ)' then tscor else 0 end) '英語(yǔ)'
from testScore
group by tname
實(shí)例二
有如下數(shù)據(jù):(為了看得更清楚,我并沒(méi)有使用國(guó)家代碼,而是直接用國(guó)家名作為Primary Key)
國(guó)家(country) | 人口(population) |
中國(guó) | 600 |
美國(guó) | 100 |
加拿大 | 100 |
英國(guó) | 200 |
法國(guó) | 300 |
日本 | 250 |
德國(guó) | 200 |
墨西哥 | 50 |
印度 | 250 |
根據(jù)這個(gè)國(guó)家人口數(shù)據(jù),統(tǒng)計(jì)亞洲和北美洲的人口數(shù)量。應(yīng)該得到下面這個(gè)結(jié)果。
洲 | 人口 |
亞洲 | 1100 |
北美洲 | 250 |
其他 | 700 |
代碼
SELECT SUM(population), CASE country WHEN '中國(guó)' THEN '亞洲' WHEN '印度' THEN '亞洲' WHEN '日本' THEN '亞洲' WHEN '美國(guó)' THEN '北美洲' WHEN '加拿大' THEN '北美洲' WHEN '墨西哥' THEN '北美洲' ELSE '其他' END FROM Table_A GROUP BY CASE country WHEN '中國(guó)' THEN '亞洲' WHEN '印度' THEN '亞洲' WHEN '日本' THEN '亞洲' WHEN '美國(guó)' THEN '北美洲' WHEN '加拿大' THEN '北美洲' WHEN '墨西哥' THEN '北美洲' ELSE '其他' END;
同樣的,我們也可以用這個(gè)方法來(lái)判斷工資的等級(jí),并統(tǒng)計(jì)每一等級(jí)的人數(shù)。SQL代碼如下;
SELECT CASE WHEN salary = 500 THEN '1' WHEN salary > 500 AND salary = 600 THEN '2' WHEN salary > 600 AND salary = 800 THEN '3' WHEN salary > 800 AND salary = 1000 THEN '4' ELSE NULL END salary_class, COUNT(*) FROM Table_A GROUP BY CASE WHEN salary = 500 THEN '1' WHEN salary > 500 AND salary = 600 THEN '2' WHEN salary > 600 AND salary = 800 THEN '3' WHEN salary > 800 AND salary = 1000 THEN '4' ELSE NULL END;
對(duì)于groupby后面一般都是跟一個(gè)列名,但在該例子中通過(guò)case語(yǔ)句使分組變得跟強(qiáng)大了。
實(shí)例三
有如下數(shù)據(jù)
國(guó)家(country) | 性別(sex) | 人口(population) |
中國(guó) | 1 | 340 |
中國(guó) | 2 | 260 |
美國(guó) | 1 | 45 |
美國(guó) | 2 | 55 |
加拿大 | 1 | 51 |
加拿大 | 2 | 49 |
英國(guó) | 1 | 40 |
英國(guó) | 2 | 60 |
按照國(guó)家和性別進(jìn)行分組,得出結(jié)果如下
國(guó)家 | 男 | 女 |
中國(guó) | 340 | 260 |
美國(guó) | 45 | 55 |
加拿大 | 51 | 49 |
英國(guó) | 40 | 60 |
代碼
SELECT country, SUM( CASE WHEN sex = '1' THEN population ELSE 0 END), --男性人口 SUM( CASE WHEN sex = '2' THEN population ELSE 0 END) --女性人口 FROM Table_A GROUP BY country;
GROUP BY子句中的NULL值處理
當(dāng)GROUP BY子句中用于分組的列中出現(xiàn)NULL值時(shí),將如何分組呢?SQL中,NULL不等于NULL(在WHERE子句中有過(guò)介紹)。然而,在GROUP BY子句中,卻將所有的NULL值分在同一組,即認(rèn)為它們是“相等”的。
HAVING子句
GROUP BY子句分組,只是簡(jiǎn)單地依據(jù)所選列的數(shù)據(jù)進(jìn)行分組,將該列具有相同值的行劃為一組。而實(shí)際應(yīng)用中,往往還需要?jiǎng)h除那些不能滿足條件的行組,為了實(shí)現(xiàn)這個(gè)功能,SQL提供了HAVING子句。語(yǔ)法如下。
SELECT column, SUM(column) FROM table GROUP BY column HAVING SUM(column) condition value
說(shuō)明:HAVING通常與GROUP BY子句同時(shí)使用。當(dāng)然,語(yǔ)法中的SUM()函數(shù)也可以是其他任何聚合函數(shù)。DBMS將HAVING子句中的搜索條件應(yīng)用于GROUP BY子句產(chǎn)生的行組,如果行組不滿足搜索條件,就將其從結(jié)果表中刪除。
HAVING子句的應(yīng)用
從TEACHER表中查詢至少有兩位教師的系及教師人數(shù)。
實(shí)現(xiàn)代碼:
SELECT DNAME, COUNT(*) AS num_teacher FROM TEACHER GROUP BY DNAME HAVING COUNT(*)>=2
HAVING子句與WHERE子句的區(qū)別
HAVING子句和WHERE子句的相似之處在于,它也定義搜索條件。但與WHERE子句不同,HAVING子句與組有關(guān),而不是與單個(gè)的行有關(guān)。
1、如果指定了GROUP BY子句,那么HAVING子句定義的搜索條件將作用于這個(gè)GROUP BY子句創(chuàng)建的那些組。
2、如果指定WHERE子句,而沒(méi)有指定GROUP BY子句,那么HAVING子句定義的搜索條件將作用于WHERE子句的輸出,并把這個(gè)輸出看作是一個(gè)組。
3、如果既沒(méi)有指定GROUP BY子句也沒(méi)有指定WHERE子句,那么HAVING子句定義的搜索條件將作用于FROM子句的輸出,并把這個(gè)輸出看作是一個(gè)組。
4、在SELECT語(yǔ)句中,WHERE和HAVING子句的執(zhí)行順序不同。在本書(shū)的5.1.2節(jié)介紹的SELECT語(yǔ)句的執(zhí)行步驟可知,WHERE子句只能接收來(lái)自FROM子句的輸入,而HAVING子句則可以接收來(lái)自GROUP BY子句、WHERE子句和FROM子句的輸入。
標(biāo)簽:來(lái)賓 池州 東營(yíng) 新鄉(xiāng) 大同 文山 濱州 黃山
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《分組后分組合計(jì)以及總計(jì)SQL語(yǔ)句(稍微整理了一下)》,本文關(guān)鍵詞 分組,后,合計(jì),以及,總計(jì),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。