SQL語句彙總(三)——聚合函數、分組、子查詢及組合查詢

原文鏈接:http://www.cnblogs.com/ghost-xyx/p/3811036.html

聚合函數:

SQL中提供的聚合函數可以用來統計、求和、求最值等等。

分類:

–COUNT:統計行數量

–SUM:獲取單個列的合計值

–AVG:計算某個列的平均值

–MAX:計算列的最大值

–MIN:計算列的最小值

 

首先,創建數據表如下:

 

 

執行列、行計數(count):

標準格式

SELECT COUNT(<計數規範>) FROM <表名>

其中,計數規範包括:

- * :計數所有選擇的行,包括NULL值;

- ALL 列名:計數指定列的所有非空值行,如果不寫,默認爲ALL;

- DISTINCT 列名:計數指定列的唯一非空值行。

例,計算班裏共有多少學生:

SELECT COUNT(*) FROM t_student;

 

也可加入篩選條件,如求女學生數目:

SELECT COUNT(*) FROM t_student WHERE student_sex='女';

如果要計算班級數目,就需要用到DISTINCT:

SELECT COUNT(DISTINCT student_class) FROM t_student;

DISTINCT即去重,如果不加DISTINCT則結果爲錶行數——5。

 

返回列合計值(SUM):

注:sum只要ALL與DISTINCT兩種計數規範,無*。

計算學生年齡之和:

SELECT SUM(student_age) FROM t_student;

 

返回列平均值(AVG):

計算學生平均年齡:

SELECT AVG(student_age)FROM t_student;

 

返回最大值/最小值(MAX/MIN):

求年齡最大的學生信息(最小值同理):

SELECT MAX(student_age) FROM t_student;

注:這裏只能求出最大年齡,要想顯示年齡最大的學生全部信息,需要用到之後的子查詢。

 

數據分組(GROUP BY):

SQL中數據可以按列名分組,搭配聚合函數十分實用。

例,統計每個班的人數:

SELECT student_class,COUNT(ALL student_name) AS 總人數 FROM t_student GROUP BY (student_class);

AS爲定義別名,別名的使用在組合及聯接查詢時會有很好的效果,之後再說。

分組中也可以加入篩選條件WHERE,不過這裏一定要注意的是,執行順序爲:WHERE過濾→分組→聚合函數。牢記!

統計每個班上20歲以上的學生人數:

SELECT student_class,COUNT(student_name) AS 總人數 FROM t_student WHERE student_age >20 GROUP BY (student_class);

 

HAVING過濾條件:

之前說了分組操作、聚合函數、WHERE過濾的執行順序,那如果我們希望在聚合之後執行過濾條件怎麼辦?

例,我們想查詢平均年齡在20歲以上的班級

能用下面的語句嗎?

SELECT student_class, AVG(student_age) FROM t_student WHERE AVG(student_age)>20 GROUP BY student_class;

結果會出錯。正因爲聚合函數在WHERE之後執行,所以這裏在WHERE判斷條件里加入聚合函數是做不到的。

這裏使用HAIVING即可完成:

SELECT student_class,AVG(student_age) AS 平均年齡 FROM t_student GROUP BY (student_class) HAVING AVG(student_age)>20; 

 

這裏再囉嗦一句

SQL的執行順序:

–第一步:執行FROM

–第二步:WHERE條件過濾

–第三步:GROUP BY分組

–第四步:執行SELECT投影列

–第五步:HAVING條件過濾

–第六步:執行ORDER BY 排序

 

子查詢:

爲什麼要子查詢?

現有一數據表如下:

根據之前的知識我們可以查出每門科目的最高分,但是要想查出取得最高分的學生信息就做不到了。這時就需要用到子查詢來取得完整的信息。

 

什麼是子查詢?子查詢就是嵌套在主查詢中的查詢。

子查詢可以嵌套在主查詢中所有位置,包括SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。

但並不是每個位置嵌套子查詢都是有意義並實用的,這裏對幾種有實際意義的子查詢進行說明。

現有表兩張:一張學生表、一張班表。id相關聯

 

在SELECT中嵌套:

學生信息和班級名稱位於不同的表中,要在同一張表中查出學生的學號、姓名、班級名稱:

SELECT s.student_id,s.student_name,(SELECT class_name FROM t_class c WHERE c.class_id=s.class_id) FROM t_student s GROUP BY s.student_id;         

* 首先這條SQL語句用到了別名,寫法爲在FORM的表名後加上某個字符比如FROM t_student s,這樣在之後調用t_student的某一列時就可以用s.student_id來強調此列來源於對應別名的那張表。

別名在子查詢及聯接查詢中的應用有着很好效果,當兩張表有相同列名或者爲了加強可讀性,給表加上不同的別名,就能很好的區分哪些列屬於哪張表。

還有種情況就是在子查詢或聯接查詢時,主查詢及子查詢均爲對同一張表進行操作,爲主、子查詢中的表加上不同的別名能夠很好的區分哪些列的操作是在主查詢中進行的,哪些列的操作是在子查詢中進行的,下文會有實例說明。

接下來回到上面的SQL語句中,可以看出本條子查詢的嵌套是在SELECT位置(括號括起來的部分),它與學號、學生姓名以逗號分隔開並列在SELECT位置,也就是說它是我們想要查出的一列,

子查詢中查出的是,班級表中的班級id與學生表中的班級id相同的行,注意 WHERE c.class_id=s.class_id 這裏就是別名用法的一個很好的體現,區分開了兩張表中同樣列名的列。

結果:

最後的GROUP BY可以理解爲對重複行的去重,如果不加:

 

在WHERE中嵌套:

現要查出C語言成績最高的學生的信息:

SELECT * FROM t_student WHERE student_subject='C語言' AND student_score>=ALL (SELECT student_score FROM t_student WHERE student_subject='C語言') ;

結果:

這裏出現了一個ALL,其爲子查詢運算符

分類:

–ALL運算符

  和子查詢的結果逐一比較,必須全部滿足時表達式的值才爲真。

–ANY運算符

  和子查詢的結果逐一比較,其中一條記錄滿足條件則表達式的值就爲真。

–EXISTS/NOT EXISTS運算符

  EXISTS判斷子查詢是否存在數據,如果存在則表達式爲真,反之爲假。NOT EXISTS相反。

在子查詢或相關查詢中,要求出某個列的最大值,通常都是用ALL來比較,大意爲比其他行都要大的值即爲最大值。

要查出C語言成績比李四高的學生的信息:

SELECT * FROM t_student WHERE student_subject='C語言' AND student_score >(SELECT student_score FROM t_student WHERE student_name='李四' AND student_subject='C語言'); 

通過上面兩例,應該可以明白子查詢在WHERE中嵌套的作用。通過子查詢中返回的列值來作爲比較對象,在WHERE中運用不同的比較運算符來對其進行比較,從而得到結果。

現在我們回到最開始的問題,怎麼查出每門課最高成績的學生的信息:

SELECT * FROM t_student s1 WHERE s1.student_score >= ALL(SELECT s2.student_score FROM t_student s2 WHERE s1.`student_subject`=s2.student_subject);

這裏就是上文提到的別名的第二種用法,主、子查詢對同一張表操作,區分開位於內外表中相同的列名。

結果:

 

子查詢的分類:

–相關子查詢

  執行依賴於外部查詢的數據。

  外部查詢返回一行,子查詢就執行一次。

–非相關子查詢

  獨立於外部查詢的子查詢。

  子查詢總共執行一次,執行完畢後後將值傳遞給外部查詢。

 

上文提到的例子中,第一個例子求學生對應班級名的即爲相關子查詢,其中WHERE c.class_id=s.class_id 即爲相關條件。其他的例子均只對一張表進行操作,爲非相關子查詢。

需要注意的是相關子查詢主查詢執行一回,子查詢就執行一回,十分耗費時間,尤其是當數據多的時候。

 

組合查詢:

通過UNION運算符來將兩張表縱向聯接,基本方式爲:

SELECT 列1 , 列2 FROM 表1
UNION
SELECT 列3 , 列4 FROM 表2;

UNION ALL爲保留重複行:

SELECT 列1 , 列2 FROM 表1
UNION ALL
SELECT 列3 , 列4 FROM 表2;

組合查詢並不是太實用,所以這裏只是簡單提一下,不舉出例子了。

 

上文說過相關子查詢不推薦使用,組合查詢又用的少之又少,那需要關聯的多張表我們怎麼做?

這就是下一篇博文要詳細說明的SQL的重點表聯接、聯接查詢。而此篇博文目的是爲了對嵌套查詢、別名的用法等等打下基礎,畢竟只是寫法變了,思路還是相似的。

 

感謝您的瀏覽,希望能對您有所幫助。

轉載於:https://www.cnblogs.com/ghost-xyx/p/3811036.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章