日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sql分组查询group by结合count,sum统计语句的实现(附带sql详细分析步骤)

發(fā)布時間:2024/1/1 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sql分组查询group by结合count,sum统计语句的实现(附带sql详细分析步骤) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

日常寫代碼經(jīng)常會遇到數(shù)據(jù)統(tǒng)計的業(yè)務(wù)場景,分組查詢 group by 結(jié)合 count 和 sum 的復(fù)雜語句寫起來容易令人頭大,在這里分享兩個比較復(fù)雜的統(tǒng)計場景,提供詳細(xì)分析思路和最終sql語句,希望能給大家?guī)韼椭?/p>

場景1:統(tǒng)計每個學(xué)生的加減分次數(shù)和總分

庫表結(jié)構(gòu)如下所示:

學(xué)生分?jǐn)?shù)表:student_score

字段名含義字段類型備注
id自增編號bigint
student_name學(xué)生姓名varchar
score分?jǐn)?shù)double
sort分?jǐn)?shù)類型int1-加分;2-減分;
is_delete刪除標(biāo)志位int默認(rèn)為0;

一上來不著急寫 sql,先來分析一下:

因為統(tǒng)計的是每個學(xué)生的分?jǐn)?shù),所以根據(jù)學(xué)生名稱 student_name 進(jìn)行 group by 分組查詢。

需要獲取的字段包括 學(xué)生名稱 student_name,加分次數(shù) add_count,扣分次數(shù) sub_count,總加分 add_score,總扣分 sub_score,其中,學(xué)生名稱不需要計算,因此只需處理次數(shù)和分?jǐn)?shù)。

我們知道,count() 主要用于求行的個數(shù)累計,所以當(dāng)分?jǐn)?shù)類型 sort 為 1,則增加加分次數(shù),sort 為 2,則增加扣分次數(shù);而 sum() 用于求和累加,因而使用 sum() 來計算總分,分?jǐn)?shù)類型 sort 為 1,則加分,sort 為 2,則減分。

有了清晰的思路,sql就不難寫了:

SELECTstudent_name,count(sort = 1 OR NULL) add_count,count(sort = 2 OR NULL) sub_count,sum(IF(sort = 1, score, 0)) add_score,sum(IF(sort = 2, score, 0)) sub_score FROMstudent_score WHEREis_delete = 0 GROUP BYstudent_name

原始表數(shù)據(jù):

統(tǒng)計結(jié)果:

這里的次數(shù)和分?jǐn)?shù)的條件判斷是通過 if 語句來實現(xiàn)的,我們也可以通過 case when 語句來實現(xiàn):

SELECTstudent_name,count(case when sort = 1 then 1 else null end) add_count,count(case when sort = 2 then 1 else null end) sub_count,sum(case when sort = 1 then score else 0 end) add_score,sum(case when sort = 2 then score else 0 end) sub_score FROMstudent_score WHEREis_delete = 0 GROUP BYstudent_name

場景2:按照權(quán)重統(tǒng)計每個學(xué)生的體測成績

體育測試中我們要根據(jù)不同的指標(biāo)對學(xué)生進(jìn)行打分,目前分為5項指標(biāo):800米,50米,立定跳遠(yuǎn),仰臥起坐和坐位體前屈。總分為100分,每項的分?jǐn)?shù)權(quán)重占比不一樣,如下表所示:

項目分?jǐn)?shù)占比(%)
800米30
50米15
立定跳遠(yuǎn)20
仰臥起坐15
坐位體前屈20

其中立定跳遠(yuǎn)需要測試3次,每次都進(jìn)行打分,需要根據(jù)這3次的得分計算出平均分作為最終得分,未來其他指標(biāo)也可能采用這種方式進(jìn)行打分。

需求明確了,先來設(shè)計數(shù)據(jù)庫表,由于每項指標(biāo)的權(quán)重是固定的,可以采用單獨一個表來存儲指標(biāo)權(quán)重:

指標(biāo)權(quán)重表:index_score

字段名含義字段類型備注
id自增編號bigint
index_code指標(biāo)編號varchar
index_name指標(biāo)名稱varchar
share指標(biāo)權(quán)重int
is_delete刪除標(biāo)志位int默認(rèn)為0;

由于庫表中需要保存全量詳細(xì)的體測記錄,所以需要記錄每個學(xué)生的指標(biāo)和對應(yīng)的評分。這里通過指標(biāo)編號進(jìn)行關(guān)聯(lián),結(jié)果記錄表如下所示:

結(jié)果記錄表:score_record

字段名含義字段類型備注
id自增編號bigint
student_name學(xué)生名稱varchar
index_code指標(biāo)編號varchar
score對應(yīng)指標(biāo)得分double
is_delete刪除標(biāo)志位int默認(rèn)為0;

我們需要通過一個sql關(guān)聯(lián) 指標(biāo)權(quán)重表結(jié)果記錄表 來獲取每個學(xué)生的姓名和總得分。這個場景比較復(fù)雜,一步一步來分析:

首先先來處理最復(fù)雜的立定跳遠(yuǎn)項,先計算每個學(xué)生的3次得分的平均分,由于未來其他指標(biāo)也可能采用這種方式進(jìn)行打分,那么我們就要根據(jù)學(xué)生姓名和指標(biāo)編號共同進(jìn)行 group by 分組后再獲取平均值:

SELECTstudent_name,index_code,round(avg(score), 1) index_avg FROMscore_record r WHEREr.is_delete = 0 GROUP BYstudent_name, index_code

原始表數(shù)據(jù):

統(tǒng)計結(jié)果:

統(tǒng)計出每個學(xué)生的各項指標(biāo)得分就完成了第一步,第二步需要根據(jù)各項指標(biāo)的權(quán)重結(jié)合得分計算總分。這就需要結(jié)合指標(biāo)權(quán)重表來獲取每項指標(biāo)的權(quán)重占比 share,再乘以第一步計算出的平均值 index_avg 后,最后使用 sum() 來計算出總分。

當(dāng)然這里需要根據(jù)學(xué)生姓名來進(jìn)行分組,對于計算出的總分還要使用 round() 函數(shù)保留兩位小數(shù),最終 sql 如下:

SELECTround(sum(s.share * t.index_avg) / 100, 2) score, t.student_name FROM(SELECTstudent_name,index_code,round(avg(score), 1) index_avgFROMscore_record rWHEREr.is_delete = 0GROUP BYstudent_name,index_code) t LEFT JOIN index_score s ON t.index_code = s.index_code GROUP BYt.student_name

統(tǒng)計結(jié)果:

這樣一個看起來有點復(fù)雜的 sql,采用從里到外逐步分析的方式,也就可以輕松寫出來了。

總結(jié)

以上是生活随笔為你收集整理的sql分组查询group by结合count,sum统计语句的实现(附带sql详细分析步骤)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。