sql分组查询group by结合count,sum统计语句的实现(附带sql详细分析步骤)
日常写代码经常会遇到数据统计的业务场景,分组查询 group by 结合 count 和 sum 的复杂语句写起来容易令人头大,在这里分享两个比较复杂的统计场景,提供详细分析思路和最终sql语句,希望能给大家带来帮助。
场景1:统计每个学生的加减分次数和总分
库表结构如下所示:
学生分数表:student_score
字段名 | 含义 | 字段类型 | 备注 |
---|---|---|---|
id | 自增编号 | bigint | |
student_name | 学生姓名 | varchar | |
score | 分数 | double | |
sort | 分数类型 | int | 1-加分;2-减分; |
is_delete | 删除标志位 | int | 默认为0; |
一上来不着急写 sql,先来分析一下:
因为统计的是每个学生的分数,所以根据学生名称 student_name 进行 group by 分组查询。
需要获取的字段包括 学生名称 student_name,加分次数 add_count,扣分次数 sub_count,总加分 add_score,总扣分 sub_score,其中,学生名称不需要计算,因此只需处理次数和分数。
我们知道,count() 主要用于求行的个数累计,所以当分数类型 sort 为 1,则增加加分次数,sort 为 2,则增加扣分次数;而 sum() 用于求和累加,因而使用 sum() 来计算总分,分数类型 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
原始表数据:
统计结果:
这里的次数和分数的条件判断是通过 if 语句来实现的,我们也可以通过 case when 语句来实现:
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:按照权重统计每个学生的体测成绩
体育测试中我们要根据不同的指标对学生进行打分,目前分为5项指标:800米,50米,立定跳远,仰卧起坐和坐位体前屈。总分为100分,每项的分数权重占比不一样,如下表所示:
项目 | 分数占比(%) |
---|---|
800米 | 30 |
50米 | 15 |
立定跳远 | 20 |
仰卧起坐 | 15 |
坐位体前屈 | 20 |
其中立定跳远需要测试3次,每次都进行打分,需要根据这3次的得分计算出平均分作为最终得分,未来其他指标也可能采用这种方式进行打分。
需求明确了,先来设计数据库表,由于每项指标的权重是固定的,可以采用单独一个表来存储指标权重:
指标权重表:index_score
字段名 | 含义 | 字段类型 | 备注 |
---|---|---|---|
id | 自增编号 | bigint | |
index_code | 指标编号 | varchar | |
index_name | 指标名称 | varchar | |
share | 指标权重 | int | |
is_delete | 删除标志位 | int | 默认为0; |
由于库表中需要保存全量详细的体测记录,所以需要记录每个学生的指标和对应的评分。这里通过指标编号进行关联,结果记录表如下所示:
结果记录表:score_record
字段名 | 含义 | 字段类型 | 备注 |
---|---|---|---|
id | 自增编号 | bigint | |
student_name | 学生名称 | varchar | |
index_code | 指标编号 | varchar | |
score | 对应指标得分 | double | |
is_delete | 删除标志位 | int | 默认为0; |
我们需要通过一个sql关联 指标权重表 和 结果记录表 来获取每个学生的姓名和总得分。这个场景比较复杂,一步一步来分析:
首先先来处理最复杂的立定跳远项,先计算每个学生的3次得分的平均分,由于未来其他指标也可能采用这种方式进行打分,那么我们就要根据学生姓名和指标编号共同进行 group by 分组后再获取平均值:
SELECTstudent_name,index_code,round(avg(score), 1) index_avg
FROMscore_record r
WHEREr.is_delete = 0
GROUP BYstudent_name, index_code
原始表数据:
统计结果:
统计出每个学生的各项指标得分就完成了第一步,第二步需要根据各项指标的权重结合得分计算总分。这就需要结合指标权重表来获取每项指标的权重占比 share,再乘以第一步计算出的平均值 index_avg 后,最后使用 sum() 来计算出总分。
当然这里需要根据学生姓名来进行分组,对于计算出的总分还要使用 round() 函数保留两位小数,最终 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
统计结果:
这样一个看起来有点复杂的 sql,采用从里到外逐步分析的方式,也就可以轻松写出来了。
sql分组查询group by结合count,sum统计语句的实现(附带sql详细分析步骤)相关推荐
- SQL语句之分组查询--GROUP BY(group by)
SQL语句之分组查询–GROUP BY(group by) 语法 select 聚合函数,列(要求出现在group by的后面)from 表where 筛选条件group by 分组的列表order ...
- SQL数据库——分组查询GROUP BY
一.分组查询GROUP BY 1.语法 SELECT (列名) as '自由命名' , COUNT(*) as '自由命名'; from (表名); GROUP BY (列名); 2. * 号里可以为 ...
- oracle分组聚合查询,Oracle中分组查询group by用法规则解析
本篇文章小编给大家分享一下Oracle中分组查询group by用法规则解析,文章介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. Oracle中group by ...
- sql语法基础,sql分组查询
01分组查询–group by 格式: SELECT 列名1,列名2,... FROM 表名 GROUP BY 列名1,列名2.... 例一,按照商品种类统计一下行数 SELECT product_t ...
- SQL分组查询和分页查询[代码+运行结果+讲解]
文章目录 前言 一.分组查询 二.分页查询 总结 前言 分组查询和分页查询也是开发中用到的对数据库表的查询操作.下述代码都是通过stu表,内容如下图: 一.分组查询 1.查询男同学和女 ...
- [转]linq to sql (Group By/Having/Count/Sum/Min/Max/Avg操作符)
本文转自:http://www.cnblogs.com/jack-liang/archive/2011/03/22/1991554.html Group By/Having操作符 适用场景:分组数据, ...
- linq to sql (Group By/Having/Count/Sum/Min/Max/Avg操作符)
Group By/Having操作符 适用场景:分组数据,为我们查找数据缩小范围. 说明:分配并返回对传入参数进行分组操作后的可枚举对象.分组:延迟 1.简单形式: var q =from p in ...
- 深入理解sql分组查询(group by)
理解group by语义 个人认为sql中的group by和join是两大难点,因为它们转换了原来的表结构,group把表按某些字段统计缩小,join则使用笛卡尔积将多个表连接展开(关于表的连接,请 ...
- SQL分组查询后取每组的前N条记录
本文由 Leon 同学授权发布 这个公众号的关注者除了大部分是 Android 工程师之外还有部分后端以及前端同学,我鼓励也非常欢迎大家来投稿,其实我们并不需要把自己限定在某个领域,多学学其他语言也是 ...
最新文章
- oracle10g 6.0更改5.2,Oracle 10G 10.2.0.1升级到10.2.0.5
- 惠普台式计算机系统系统修复,惠普电脑系统如何恢复【方法步骤】
- 爬虫从入门到放弃 - 纯新手学习-爬虫基本原理
- 震惊!温州一程序员编完八皇后吐血而亡,他的代码是什么样子?!!
- UVa 11136 - Hoax or what
- 某音爆火,人物头像动漫化,为女朋友打造独一无二的头像【python实战:人物图片动漫化】
- vue项目中跨域问题的解决
- 使用python来读取超大型文件数据
- javaweb——EL表达式和JSTL
- Java代理(proxy)
- mac sz rz file tras
- 阿里云香港服务器和大陆服务器的优缺点分析
- win7右下角显示此windows副本不是正版
- DSP芯片TMS320F2812之ADC模块的说明及使用步骤
- Vue3 Mixin的使用方法(全局,局部,setup内部使用)
- kjb文件 解析_在Linux上使用lnav监控和分析Apache日志文件工具
- shell 字符串列表长度
- window 10系统修改C盘用户名过程
- css实现内容两端对齐
- 华为面向5G的室内覆盖数字化概述
热门文章
- android 7.1 字体大小设置,一加3t官方更新氢的Android 7.1.1,妥妥的第一时间换上クレPro 字体...
- Consistency Regularization for GANs
- 关于开源授权协议 GPL 和 LGPL
- 由浅入深玩转华为WLAN—-6 直连二层组网+直接转发方式组网
- 哔哩哔哩推荐策略分析与思考
- java 服务器下载APK文件
- xf-calendar_plugin.js 日历完整代码
- 半年培训年薪百万?深度解析人工智能、大数据培训班背后的真相
- Vivado 多路选择器(含测试代码)
- 研究War3编辑器(7):在触发器中使用JASS脚本