SQL语句汇总(三)——聚合函数、分组、子查询及组合查询
聚合函數(shù):
SQL中提供的聚合函數(shù)可以用來(lái)統(tǒng)計(jì)、求和、求最值等等。
分類(lèi):
–COUNT:統(tǒng)計(jì)行數(shù)量 –SUM:獲取單個(gè)列的合計(jì)值 –AVG:計(jì)算某個(gè)列的平均值 –MAX:計(jì)算列的最大值 –MIN:計(jì)算列的最小值 首先,創(chuàng)建數(shù)據(jù)表如下: 執(zhí)行列、行計(jì)數(shù)(count): 標(biāo)準(zhǔn)格式 SELECT COUNT(<計(jì)數(shù)規(guī)范>) FROM <表名>其中,計(jì)數(shù)規(guī)范包括:
- * :計(jì)數(shù)所有選擇的行,包括NULL值;
- ALL 列名:計(jì)數(shù)指定列的所有非空值行,如果不寫(xiě),默認(rèn)為ALL;
- DISTINCT 列名:計(jì)數(shù)指定列的唯一非空值行。
例,計(jì)算班里共有多少學(xué)生: SELECT COUNT(*) FROM t_student;?
也可加入篩選條件,如求女學(xué)生數(shù)目:
SELECT COUNT(*) FROM t_student WHERE student_sex='女'; 如果要計(jì)算班級(jí)數(shù)目,就需要用到DISTINCT: SELECT COUNT(DISTINCT student_class) FROM t_student;DISTINCT即去重,如果不加DISTINCT則結(jié)果為表行數(shù)——5。
返回列合計(jì)值(SUM): 注:sum只要ALL與DISTINCT兩種計(jì)數(shù)規(guī)范,無(wú)*。 計(jì)算學(xué)生年齡之和: SELECT SUM(student_age) FROM t_student;?
返回列平均值(AVG):
計(jì)算學(xué)生平均年齡:
SELECT AVG(student_age)FROM t_student;?
返回最大值/最小值(MAX/MIN):
求年齡最大的學(xué)生信息(最小值同理):
SELECT MAX(student_age) FROM t_student;注:這里只能求出最大年齡,要想顯示年齡最大的學(xué)生全部信息,需要用到之后的子查詢(xún)。
?
數(shù)據(jù)分組(GROUP BY):
SQL中數(shù)據(jù)可以按列名分組,搭配聚合函數(shù)十分實(shí)用。
例,統(tǒng)計(jì)每個(gè)班的人數(shù):
SELECT student_class,COUNT(ALL student_name) AS 總?cè)藬?shù) FROM t_student GROUP BY (student_class);AS為定義別名,別名的使用在組合及聯(lián)接查詢(xún)時(shí)會(huì)有很好的效果,之后再說(shuō)。
?
分組中也可以加入篩選條件WHERE,不過(guò)這里一定要注意的是,執(zhí)行順序?yàn)?#xff1a;WHERE過(guò)濾→分組→聚合函數(shù)。牢記!
統(tǒng)計(jì)每個(gè)班上20歲以上的學(xué)生人數(shù):
SELECT student_class,COUNT(student_name) AS 總?cè)藬?shù) FROM t_student WHERE student_age >20 GROUP BY (student_class);?
HAVING過(guò)濾條件:
之前說(shuō)了分組操作、聚合函數(shù)、WHERE過(guò)濾的執(zhí)行順序,那如果我們希望在聚合之后執(zhí)行過(guò)濾條件怎么辦?
例,我們想查詢(xún)平均年齡在20歲以上的班級(jí)
能用下面的語(yǔ)句嗎?
SELECT student_class, AVG(student_age) FROM t_student WHERE AVG(student_age)>20 GROUP BY student_class; 結(jié)果會(huì)出錯(cuò)。正因?yàn)榫酆虾瘮?shù)在WHERE之后執(zhí)行,所以這里在WHERE判斷條件里加入聚合函數(shù)是做不到的。 這里使用HAIVING即可完成: SELECT student_class,AVG(student_age) AS 平均年齡 FROM t_student GROUP BY (student_class) HAVING AVG(student_age)>20; 這里再啰嗦一句 SQL的執(zhí)行順序: –第一步:執(zhí)行FROM –第二步:WHERE條件過(guò)濾 –第三步:GROUP BY分組 –第四步:執(zhí)行SELECT投影列 –第五步:HAVING條件過(guò)濾 –第六步:執(zhí)行ORDER BY 排序 子查詢(xún): 為什么要子查詢(xún)? 現(xiàn)有一數(shù)據(jù)表如下: 根據(jù)之前的知識(shí)我們可以查出每門(mén)科目的最高分,但是要想查出取得最高分的學(xué)生信息就做不到了。這時(shí)就需要用到子查詢(xún)來(lái)取得完整的信息。 什么是子查詢(xún)?子查詢(xún)就是嵌套在主查詢(xún)中的查詢(xún)。 子查詢(xún)可以嵌套在主查詢(xún)中所有位置,包括SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。 但并不是每個(gè)位置嵌套子查詢(xún)都是有意義并實(shí)用的,這里對(duì)幾種有實(shí)際意義的子查詢(xún)進(jìn)行說(shuō)明。 現(xiàn)有表兩張:一張學(xué)生表、一張班表。id相關(guān)聯(lián) 在SELECT中嵌套: 學(xué)生信息和班級(jí)名稱(chēng)位于不同的表中,要在同一張表中查出學(xué)生的學(xué)號(hào)、姓名、班級(jí)名稱(chēng): 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語(yǔ)句用到了別名,寫(xiě)法為在FORM的表名后加上某個(gè)字符比如FROM t_student s,這樣在之后調(diào)用t_student的某一列時(shí)就可以用s.student_id來(lái)強(qiáng)調(diào)此列來(lái)源于對(duì)應(yīng)別名的那張表。
別名在子查詢(xún)及聯(lián)接查詢(xún)中的應(yīng)用有著很好效果,當(dāng)兩張表有相同列名或者為了加強(qiáng)可讀性,給表加上不同的別名,就能很好的區(qū)分哪些列屬于哪張表。
還有種情況就是在子查詢(xún)或聯(lián)接查詢(xún)時(shí),主查詢(xún)及子查詢(xún)均為對(duì)同一張表進(jìn)行操作,為主、子查詢(xún)中的表加上不同的別名能夠很好的區(qū)分哪些列的操作是在主查詢(xún)中進(jìn)行的,哪些列的操作是在子查詢(xún)中進(jìn)行的,下文會(huì)有實(shí)例說(shuō)明。
接下來(lái)回到上面的SQL語(yǔ)句中,可以看出本條子查詢(xún)的嵌套是在SELECT位置(括號(hào)括起來(lái)的部分),它與學(xué)號(hào)、學(xué)生姓名以逗號(hào)分隔開(kāi)并列在SELECT位置,也就是說(shuō)它是我們想要查出的一列, 子查詢(xún)中查出的是,班級(jí)表中的班級(jí)id與學(xué)生表中的班級(jí)id相同的行,注意?WHERE c.class_id=s.class_id?這里就是別名用法的一個(gè)很好的體現(xiàn),區(qū)分開(kāi)了兩張表中同樣列名的列。 結(jié)果: 最后的GROUP BY可以理解為對(duì)重復(fù)行的去重,如果不加: 在WHERE中嵌套: 現(xiàn)要查出C語(yǔ)言成績(jī)最高的學(xué)生的信息: SELECT * FROM t_student WHERE student_subject='C語(yǔ)言' AND student_score>=ALL (SELECT student_score FROM t_student WHERE student_subject='C語(yǔ)言') ;結(jié)果:
這里出現(xiàn)了一個(gè)ALL,其為子查詢(xún)運(yùn)算符 分類(lèi): –ALL運(yùn)算符 和子查詢(xún)的結(jié)果逐一比較,必須全部滿(mǎn)足時(shí)表達(dá)式的值才為真。 –ANY運(yùn)算符 和子查詢(xún)的結(jié)果逐一比較,其中一條記錄滿(mǎn)足條件則表達(dá)式的值就為真。 –EXISTS/NOT EXISTS運(yùn)算符 EXISTS判斷子查詢(xún)是否存在數(shù)據(jù),如果存在則表達(dá)式為真,反之為假。NOT EXISTS相反。 在子查詢(xún)或相關(guān)查詢(xún)中,要求出某個(gè)列的最大值,通常都是用ALL來(lái)比較,大意為比其他行都要大的值即為最大值。 要查出C語(yǔ)言成績(jī)比李四高的學(xué)生的信息: SELECT * FROM t_student WHERE student_subject='C語(yǔ)言' AND student_score >(SELECT student_score FROM t_student WHERE student_name='李四' AND student_subject='C語(yǔ)言');通過(guò)上面兩例,應(yīng)該可以明白子查詢(xún)?cè)赪HERE中嵌套的作用。通過(guò)子查詢(xún)中返回的列值來(lái)作為比較對(duì)象,在WHERE中運(yùn)用不同的比較運(yùn)算符來(lái)對(duì)其進(jìn)行比較,從而得到結(jié)果。
現(xiàn)在我們回到最開(kāi)始的問(wèn)題,怎么查出每門(mén)課最高成績(jī)的學(xué)生的信息:
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);這里就是上文提到的別名的第二種用法,主、子查詢(xún)對(duì)同一張表操作,區(qū)分開(kāi)位于內(nèi)外表中相同的列名。
結(jié)果:
?
子查詢(xún)的分類(lèi):
–相關(guān)子查詢(xún) 執(zhí)行依賴(lài)于外部查詢(xún)的數(shù)據(jù)。 外部查詢(xún)返回一行,子查詢(xún)就執(zhí)行一次。 –非相關(guān)子查詢(xún) 獨(dú)立于外部查詢(xún)的子查詢(xún)。 子查詢(xún)總共執(zhí)行一次,執(zhí)行完畢后后將值傳遞給外部查詢(xún)。 上文提到的例子中,第一個(gè)例子求學(xué)生對(duì)應(yīng)班級(jí)名的即為相關(guān)子查詢(xún),其中WHERE c.class_id=s.class_id 即為相關(guān)條件。其他的例子均只對(duì)一張表進(jìn)行操作,為非相關(guān)子查詢(xún)。 需要注意的是相關(guān)子查詢(xún)主查詢(xún)執(zhí)行一回,子查詢(xún)就執(zhí)行一回,十分耗費(fèi)時(shí)間,尤其是當(dāng)數(shù)據(jù)多的時(shí)候。?
組合查詢(xún):
通過(guò)UNION運(yùn)算符來(lái)將兩張表縱向聯(lián)接,基本方式為:
SELECT 列1 , 列2 FROM 表1 UNION SELECT 列3 , 列4 FROM 表2;UNION ALL為保留重復(fù)行:
SELECT 列1 , 列2 FROM 表1 UNION ALL SELECT 列3 , 列4 FROM 表2; 組合查詢(xún)并不是太實(shí)用,所以這里只是簡(jiǎn)單提一下,不舉出例子了。 上文說(shuō)過(guò)相關(guān)子查詢(xún)不推薦使用,組合查詢(xún)又用的少之又少,那需要關(guān)聯(lián)的多張表我們?cè)趺醋?#xff1f; 這就是下一篇博文要詳細(xì)說(shuō)明的SQL的重點(diǎn)表聯(lián)接、聯(lián)接查詢(xún)。而此篇博文目的是為了對(duì)嵌套查詢(xún)、別名的用法等等打下基礎(chǔ),畢竟只是寫(xiě)法變了,思路還是相似的。轉(zhuǎn)載于:https://www.cnblogs.com/freeitlzx/p/10946534.html
總結(jié)
以上是生活随笔為你收集整理的SQL语句汇总(三)——聚合函数、分组、子查询及组合查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: iOS 获取屏幕最上层window以及响
- 下一篇: haproxy对mysql集群进行负载均