1. 程式人生 > >Sql Service的藝術(三) SQL聚合函數的應用

Sql Service的藝術(三) SQL聚合函數的應用

包括 不同 過程 接下來 日期 p s 不可 tno 函數名

SQL提供的聚合函數有求和,最大值,最小值,平均值,計數函數等。

聚合函數及其功能:

函數名稱 函數功能
SUM() 返回選取結果集中所有值的總和
MAX() 返回選取結果集中所有值的最大值
MIN() 返回選取結果集中所有值的最小值
AVG() 返回選取結果集中所有值的平均值
COUNT() 返回選取結果集中行的數目

  學習本節所需要的兩張表:

CREATE TABLE TEACHER
(
    ID INT IDENTITY (1,1) PRIMARY KEY ,  --主鍵,自增長
    TNO INT NOT NULL, --教工號
    TNAME CHAR(
10) NOT NULL, --教師姓名 CNO INT NOT NULL, --課程號 SAL INT, --工資 DNAME CHAR(10) NOT NULL, --所在系 TSEX CHAR(2) NOT NULL, --性別 AGE INT NOT NULL --年齡 ) INSERT INTO dbo.TEACHER VALUES( 1,王軍,4,400,數學,,32) INSERT INTO dbo.TEACHER VALUES( 2,李彤,5,6600,生物,,54) INSERT INTO dbo.TEACHER VALUES(
3,王永軍,1,1000,計算機,,45) INSERT INTO dbo.TEACHER VALUES( 4,劉曉婧,2,8000,計算機,,23) INSERT INTO dbo.TEACHER VALUES( 5,高維,8,6000,電子工程,,54) INSERT INTO dbo.TEACHER VALUES( 6,李偉,7,230,機械工程,,23) INSERT INTO dbo.TEACHER VALUES( 7,劉輝,3,0,生物,,65) INSERT INTO dbo.TEACHER VALUES( 8,劉偉,9,500,
計算機,,23) INSERT INTO dbo.TEACHER VALUES( 9,劉靜,12,0,經濟管理,,45) INSERT INTO dbo.TEACHER VALUES( 10,劉奕鍇,13,70000,計算機,,65) INSERT INTO dbo.TEACHER VALUES( 11,高維,14,70000,經濟管理,,61) CREATE TABLE COURSE ( ID INT IDENTITY (1,1) PRIMARY KEY , --主鍵,自增長 CNO INT NOT NULL, --課程號 CNAME CHAR(30) NOT NULL, --課程名稱 CTIME INT NOT NULL, --學時 SCOUNT INT NOT NULL, --容納人數 CTEST SMALLDATETIME NOT NULL, --考試時間 ) INSERT INTO dbo.COURSE VALUES( 4,應用數學基礎,48,120,2006-7-10) INSERT INTO dbo.COURSE VALUES( 5,生物工程概論,32,80,2006-7-8) INSERT INTO dbo.COURSE VALUES( 1,計算機軟件基礎,32,70,2006-7-8) INSERT INTO dbo.COURSE VALUES( 2,計算機硬件基礎,24,80,2006-6-28) INSERT INTO dbo.COURSE VALUES( 8,模擬電路設計,28,90,2006-7-10) INSERT INTO dbo.COURSE VALUES( 7,機械設計實踐,48,68,2006-7-14) INSERT INTO dbo.COURSE VALUES( 3,生物化學,32,40,2006-7-2) INSERT INTO dbo.COURSE VALUES( 9,數據庫設計,16,80,2006-7-1) INSERT INTO dbo.COURSE VALUES( 6,設計理論,28,45,2006-6-30) INSERT INTO dbo.COURSE VALUES( 10,計算機入門,25,150,2006-6-29) INSERT INTO dbo.COURSE VALUES( 11,數字電路設計基礎,30,125,2006-6-20) INSERT INTO dbo.COURSE VALUES( 12,數字電路設計基礎%,30,125,2006-6-20) INSERT INTO dbo.COURSE VALUES( 13,_設計理論,28,45,2006-6-30)

  

  一、求和函數——SUM()

--求所有老師的工資總和
    SELECT SUM(SAL) AS TOTAL_SAL FROM dbo.TEACHER

  註意:

    SUM()函數只能作用於數值類型數據。

     對某列求和,如果存在NULL值,則SUM函數會忽略該值。

  二、計數函數——COUNT()

   --使用COUNT(),對表的總行數
    SELECT COUNT(*) AS TOTAL FROM dbo.TEACHER

    --使用COUNT(),對表列的數據計數
    --SAL列有一行數據為空,所以結果與其他兩列不同
    SELECT COUNT(TNAME) AS TOTAL,COUNT(SAL) AS TOTAL,COUNT(DNAME) AS TOTAL FROM dbo.TEACHER

    --使用COUNT(),對表的列的數據一起包含查詢,需要用到CAST,以及"+"連接符
    --ZongLie 是包含SAL和TNAME兩列的數據,放在一起查詢的
    SELECT COUNT(TNAME) AS Total_Name,COUNT(SAL) AS Total_Sal,COUNT(DNAME) AS Total_Name,COUNT(CAST(SAL AS VARCHAR(10))+TNAME) AS ZongLie FROM dbo.TEACHER

    --使用COUNT(),滿足where條件的查詢
    SELECT COUNT(*) AS TOTAL FROM dbo.TEACHER WHERE TSEX=

  註意一下兩點:

    COUNT(*),計算表中行的總數,即使表中行的數據為null,也被計入在內。
    COUNT(column),計算column列包含行的數目,如果該列中某行數據為null,則該行不計入總數。

  三、最大/最小值函數——MAX()/MIN()

    --MAX()的使用,查詢工資最高/最低
    SELECT MAX(SAL) AS 最高工資,MIN(SAL) AS 最低工資 FROM dbo.TEACHER

    --以下是兩種錯誤的寫法,聚合函數的處理是數據組,他將teacher看作是一個組,而TNAME,SAL的數據沒有進行分組,所以select語句沒有邏輯意義。
    --該列沒有包含在聚合函數或 GROUP BY 子句中。
    SELECT TNAME,MAX(SAL) FROM dbo.TEACHER
    --聚合不應出現在 WHERE 子句中,除非該聚合位於 HAVING 子句或選擇列表所包含的子查詢中,並且要對其進行聚合的列是外部引用。
    SELECT * FROM dbo.TEACHER WHERE AGE=MAX(AGE)

    --那麽接下來演示正確子句使用MAX/MIN查詢
    --子句中要寫完整的select查詢語句
    SELECT TNO,TNAME,SAL,DNAME,AGE FROM dbo.TEACHER WHERE AGE=(SELECT MAX(AGE) FROM dbo.TEACHER)  --顯示年齡最大老師的信息

    --MAX()/MIN()不僅可以用作於數值類型數據,也可以用作於字符串或者日期類型
    --字符串類型是根據字母A~Z排序的:
    SELECT MAX(TNAME) FROM dbo.TEACHER   --結果:王永軍   開頭字母:W

    --MAX()/MIN()用於時間類型
    SELECT MAX(CTEST) AS 近,MIN(CTEST) AS 遠 FROM dbo.COURSE

  註意:

    確認列中的最大值/最小值時,MAX,MIN函數會忽略NULL值。但是,如果該列所有行的值都是NULL,則函數返回NULL。

  四、均值函數--AVG()

    --均值函數是用來計算列的數據平均值的,跟SUM()一樣,只能用來計算數值類型
    SELECT AVG(SAL) FROM dbo.TEACHER     --計算工資的平均值

    --利用COUNT() SUM() AVG()來看下求平均值的過程
    SELECT AVG(SAL) AS AVG函數算的平均工資,COUNT(*) AS 總人數,SUM(SAL)/COUNT(TNAME) AS 總的工資除總的人數 FROM dbo.TEACHER
    --運行結果發現,AVG算的平均工資跟手動算的不一樣,因為AVG算平均工資的時候忽略了“NULL”,所排除了一個人數,
    --而我們平常不管有沒有工資,都要把這個人算上在求平均,所以導致結果不一樣,網上也有有不同說法,可自行斟酌,僅代表個人想法
    
    SELECT SUM(SAL) AS 工資總和 FROM dbo.TEACHER   --162730   162730/12=13560  
    SELECT COUNT(SAL) AS 工資列的總行數排除NULL FROM dbo.TEACHER   --11     162730/11=14793 工資有一個為空,忽略
    SELECT COUNT(TNAME) AS 人數列的總行數排除NULL FROM dbo.TEACHER  --12
    SELECT COUNT(*) AS 表的總行數 FROM dbo.TEACHER  --12
    SELECT * FROM dbo.TEACHER  --表數據

    --帶where子句使用條件限制平均值
    SELECT AVG(SAL) FROM dbo.TEACHER WHERE DNAME=電子工程   --這個結果同上
    SELECT * FROM dbo.TEACHER WHERE DNAME=電子工程 

    --聚合分析的重值處理
    SELECT COUNT(ALL SAL) AS 所有的 FROM dbo.TEACHER
    SELECT COUNT(DISTINCT SAL) AS 除去重復的 FROM dbo.TEACHER
    SELECT * FROM dbo.TEACHER  --表數據
    --使用ALL後,計算出所有行數,使用distinct後,排除了重復的數值
    --除了"COUNT(*)"函數外,其他函數在計算的過程中都忽略了NULL,排除NULL進行分析計算

    --聚合函數也可以組合使用,即在一條select語句中,可以使用多個聚合函數
    SELECT COUNT(*) AS 行數,MIN(AGE) AS 最小年齡,MAX(SAL) AS 最高工資,AVG(AGE) AS 平均年齡,SUM(SAL)/COUNT(*) AS 平均工資 FROM dbo.TEACHER

  五、組合查詢GROUP BY,HAVING

--GROUP BY子句分組查詢
    SELECT TSEX+教師 AS 老師,AVG(SAL) AS 平均工資 FROM dbo.TEACHER GROUP BY TSEX  --男 女老師的平均工資
    --來分析一下DBMS執行實例的步驟
    --首先執行FROM子句,將表TEACHER作為中間表
    --如果有WHERE子句,DBMS則根據其中的搜索條件,從中間表中去除那些值為False的列.這裏沒有WHERE子句,所以DBMS跳過了這個步驟
    --根據GROUP BY子句制定的分組列即TSEX,DBMS將中間表中的數據進行分組。這裏TSEX的值為‘男’,另一組中TSEX值為‘女’
    --DBNS為每個行組計算SELECT子句中的值,並為每組生成查詢結果中的一行。對於TSEX值為‘男’的行組,SELECT子句首先執行‘TSEX+教師’,得到‘男教師’列值,再執行‘AVG(SAL)’,求得該行組中的SAL的均值,將這兩個值作為結果表中的一條記錄;同樣,對TESX值為‘女’的行組,進行類似的操作得到另一條記錄

    --GROUP BY子句根據多列組合行
    SELECT DNAME,TSEX,COUNT(*) AS 人數 FROM dbo.TEACHER GROUP BY DNAME,TSEX   --查詢各系男女老師的人數
    --會發現有的沒有男或女,因為沒有值,系統默認為NULL,不顯示了

    --GROUP BY子句中的NULL處理
    SELECT SAL AS 工資,COUNT(*) AS 數量 FROM dbo.TEACHER GROUP BY SAL

    --HAVING子句
    --GROUP BY子句會根據所選的列進行分組,但實際上,我們往往還需要刪除那些不滿足條件的行組,為了實現這個功能SQL提供了HAVING子句。
    --通常GROUP BY與HAVING使用
    SELECT DNAME AS 系,COUNT(*) AS 數量 FROM dbo.TEACHER GROUP BY DNAME HAVING COUNT(*)>=2   --選擇系的數量大於等2
    --如果指定了GROUP BY子句,那麽HAVING子句定義的搜索條件將作用於這個GROUP BY子句創建的那些組
    --如果指定的WHERE子句而沒有指定GROUP BY子句,那麽HAVING子句定義的搜索條件將作用於WHERE子句的輸出,並把這個輸出看作是一個組
    --如果既沒有指定GROUP BY子句也沒有指定WHERE子句,那麽HAVING子句定義的搜索條件將作用於FROM子句的輸出並把這個輸出看作一個組
    SELECT * FROM dbo.TEACHER

    --HAVING與where子句不同的作用
    SELECT DNAME AS 系,COUNT(TSEX) AS 數量 FROM dbo.TEACHER WHERE TSEX= GROUP BY DNAME   --女老師的系擁有女老師的數量
    --不能把單個的TSEX的值應用於組,包括HAVING子句中的列必須是組列。因此,在這種情況下,WHERE子句就不可能用HAVING子句代替
    --在數據的分組聚合分析中,HAVING子句與WHERE子句也可以共存。WHERE子句在分組之前過濾,而HAVING子句則過濾分組後的數據

    SELECT DNAME AS 系,COUNT(TSEX) AS 數量 FROM dbo.TEACHER WHERE TSEX= GROUP BY DNAME HAVING COUNT(TSEX)>=2  --女老師的系擁有至少2個女老師的數量
    --通常情況下,HANVING子句都與GROUP BY子句一起使用,這樣就可以聚合相關數據,然後篩選這些數據,以進一步細化搜索。但如果沒有GROUP BY子句,HAVING子句也可以單獨使用。


    --HAVING子句的單獨使用
    SELECT COUNT(TSEX) FROM dbo.TEACHER WHERE TSEX= HAVING COUNT(TSEX)>3  --數量大於3的女老師

  註意:

    GROUP BY子句依據column列裏的數據對行進行分組,即具有相同值得行被劃為一組。它一般與聚合函數同時使用。當然,這裏的SUM函數也可以是其他聚合函數。
    所有的組合列(GROUP BY子句中列出的列)必須來自於FROM子句列出的表,不能根據實際值、聚合函數結果或者其他表達式計算的值來對行分組。

  來總結一下SELECT語句查詢子句:

  SELECT語句查詢子句及其所有子句

順序號 子句關鍵詞 子句功能
1 SELECT 從指定表中取出指定列的數據
2 FROM 制定要查詢操作的表
3 WHERE 用來規定一種選擇查詢的標準
4 GROUP BY 對結果集進行分組,常與聚合函數一起使用
5 HAVING 返回選取的結果集中行的數目
6 ORDER BY 指定分組的搜尋條件

  如果在同一個SELECT語句中用到上表的一下查詢子句,則各查詢順序排列由低到高的順序。因此,完整的SELECT查詢語句可以如下:

    --SELECT select_list
    --FROM table_source
    --[WHERE search_condition]
    --[GROUP BY group_by_expression]
    --[HAVING search_condition]
    --[ORDER BY order_expression [ASC \ DESC]]
    --[]是可選項

--至少有兩名女教師的系擁有的女教師數量,並且按數量排序 SELECT DNAME AS 系名,COUNT(TSEX) AS 數量 FROM dbo.TEACHER WHERE TSEX
= GROUP BY DNAME HAVING COUNT(TSEX)>=2 ORDER BY 數量

Sql Service的藝術(三) SQL聚合函數的應用