常见的统计解决方案
来源:SegmentFault
时间:2023-01-14 10:45:59 266浏览 收藏
在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是数据库学习者,那么本文《常见的统计解决方案》就很适合你!本篇内容主要包括常见的统计解决方案,希望对大家的知识积累有所帮助,助力实战开发!
最近用MySQL做统计的需求比较多,这里整理一些常用的场景方便后期查阅,同时也是抛砖引玉的过程。其中包括普通的分组统计,连续的每日统计,区间范围统计。
技术:MySQL, SpringDataJpa, Kotlin
说明:文章前半部分是场景分析,后半部分是语法分析
要点:GROUP BY, UNION, DATE_FORMAT, 流程控制函数
普通分组统计
场景一:根据订单状态统计订单数量。
一个很常见,也很简单的统计需求。其中状态字段是订单实体的一个属性。参考代码:(Kotlin语法)
@Query("SELECT status, COUNT(id) FROM Order GROUP BY status")
fun summaryOrderByStatus(): Array>?
场景二:根据订单中商品类目统计订单数量和金额。
比场景一稍微麻烦了一点,商品字段是订单实体的一个属性,而类目字段才是商品实体的一个属性。参考代码:(Kotlin语法)
@Query("SELECT commodity.category, COUNT(id), SUM(finalPrice) FROM Order GROUP BY commodity.category")
fun summaryOrderByCommodityCategory(): Array>?
小结:
一)、分组统计少不了GROUP BY语句,如果需要加查询条件,请在其前面添加 WHERE 语句。
二)、统计数量用COUNT,统计总和用SUM函数,有GROUP BY的地方,少不了这些聚合函数。
三)、统计返回的结果是字符串类型的二维数组。
四)、以内嵌属性分组,如果是SpringDataJpa框架,则可以直接通过"实体类.属性名"的方式。
每日统计
在做每日,每周,每月统计时,遇到返回日期不是连续的情况。原因是数据库中没有值,而我们理想状态应该是:如果没有值则默认为零,使其数据是连续的日期。
场景三:统计结果日期可能不连续
如果数据库中某个时间段没有值,那统计出来的结果会缺这段时间。参考代码:(sql语句)
-- 统计每日 SELECT DATE_FORMAT(create_date,'%Y-%m-%d') as days, COUNT(id) count FROM order GROUP BY days; -- 统计每周 SELECT DATE_FORMAT(create_date,'%Y-%u') as weeks, COUNT(id) count FROM order GROUP BY weeks; -- 统计每月 SELECT DATE_FORMAT(create_date,'%Y-%m') as months, COUNT(id) count FROM order GROUP BY months;
场景四:统计结果日期连续
要让日期连续,又要代码优雅。说实话,困扰了我很久,一直没有找到很好的解决方法,虽然目前这个方法很挫。但可以解决问题。毕竟抓到老鼠的都是好猫。如果各位有好的建议,望赐教!
解决思路:
第一步:创建一张date_summary辅助表,字段只需要有date和count(默认值为零)。
第二步:先向date_summary表插入10年内的数据。
第三步:通过UNION ALL 联合查询,将空缺的日期补上。
第二步参考代码(Kotlin语法)
val startDate = Calendar.getInstance() startDate.set(2018, 6, 1) val startTIme = startDate.timeInMillis val endDate = Calendar.getInstance() endDate.set(2028, 11, 30) val endTime = endDate.timeInMillis val oneDay = 1000 * 60 * 60 * 24L var time = startTIme val dates: MutableList= arrayListOf() while (time
第三步统计每日的SQL语句
SELECT
summary.oneDay,
summary.count
FROM
(
SELECT
DATE_FORMAT( created_date, '%Y-%m-%d' ) oneDay,
COUNT(id) count
FROM
service_order
WHERE created_date BETWEEN "2018-06-01" and "2018-08-01"
GROUP BY oneDay
UNION ALL
(
SELECT
DATE_FORMAT( date, '%Y-%m-%d' ) templateDay,
count
FROM
date_summary
WHERE date BETWEEN "2018-06-01" and "2018-08-01"
GROUP BY
templateDay
)
) summary
GROUP BY
summary.oneDay
ORDER BY
summary.oneDay ASC
小结:
一)、MySQL的DATE_FORMAT(date,format) 函数用于以不同的格式显示日期/时间数据,文章后面会详细介绍
二)、MySQL的UNION 操作符用于合并两个或多个SELECT语句的结果集,文章后面会详细介绍
区间范围统计
这是一个较为常见的需求,比如按照年龄段统计人员分布情况,甚至要求分别统计男女人数分布情况。
场景五:根据小区年龄段统计人数
只根据年龄范围统计,没有其他限制条件,使用SUM只需要加一。
SELECT INTERVAL(age,10,20,30,40,50,60,70,80,90) AS ageRatio, SUM(1) AS count FROM user GROUP BY ageRatio
场景六:根据小区年龄段统计男女人数
在场景五的基础上多了一个区分性别,用流程控制函数来设置SUM加一的情况。
SELECT INTERVAL(age,10,20,30,40,50,60,70,80,90) AS ageRatio, SUM(CASE WHEN sex=1 THEN 1 ELSE 0 END) AS male, SUM(CASE WHEN sex=0 THEN 1 ELSE 0 END) AS female FROM user GROUP BY ageRatio
小结:
一)、通过区间统计需要使用MySQL的INTERVAL函数,第一个参数是需要比较的字段,后面是比较的区间,值必须从小到大
二)、区间统计的结果也是二维数组,注意返回的结果可能不是连续的(这里的不连续可以用代码解决,毕竟区间数量较少)。第一个参数返回的是区间的下标,从0开始。
三)、当age的值在区间范围内就SUM加一,也可以通过流程控制函数(CASE WHEN THEN ELSE END)来判断是加一还是加零
MySQL知识点
知道现在都是快餐文化,大家都很忙,很少有时间去揣摩各语法的特点。所以先把常用的场景写在前面,语法知识写在后面。
GROUP BY 分组
一)、分组一般与聚合函数一起使用如SUM,COUNT等
二)、GROUP BY 在WHERE 语句之后
DATE_FORMAT 时间格式化
一)、用来修改时间的格式
二)、语法格式: DATE_FORMAT(date,format) date必须是合格的时间参数,format是输出时间格式
三)、常见的format格式有:
- %Y: 4位数的年,
- %y: 2位数的年,
- %m: 2位数的月(00~12),
- %M: 英文单词的月,
- %d: 2位数的日(00~31),
- %u: 周,星期一是一周的第一条,
- 更多可以访问w3school
UNION 联合结果
一)、UNION可以合并、联合,将多次查询结果合并成一个结果,通过查询结果合并解决了统计不连续的情况。
二)、多条查询语句的列数必须一致,各列的顺序最好一致。场景四中,两条sql都只查询了date和count,且顺序保持一致。
三)、union 去重,union all包含重复项
INTERVAL 比较间距
一)、INTERVAL()函数是比较列表(N, arg1, arg2, arg3...argN)中的N值。 一)、case when then else end 是流程控制函数中的一种,还有一种是if函数 文章到这里就结束了。如果文章对你有帮助,可以点个"推荐",也可以"关注"我,获得更多丰富的知识。若文中有什么不对或者不严谨的地方,请指正。 以上就是《常见的统计解决方案》的详细内容,更多关于mysql的资料请关注golang学习网公众号!
二)、INTERVAL()函数如果N流程控制函数
二)、使用语法:case
when 条件1 then 值1
when 条件2 then 值2
...
else 值n
end
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
数据库 · MySQL | 2天前 | 性能优化 · 执行计划 · MySQL教程 · 慢查询治理 · 数据库运维 · mysql GROUP BY优化 TempTable 内部临时表 Created_tmp_disk_tables267 收藏
-
数据库 · MySQL | 2天前 | 性能优化 · InnoDB · MySQL教程 · 数据库运维 · 高并发写入 · mysql innodb 批量写入 Change Buffer innodb_change_buffering270 收藏
-
数据库 · MySQL | 5天前 | 性能优化 · 高并发 · InnoDB · MySQL教程 · 数据库运维 · mysql innodb AUTO_INCREMENT 高并发写入 innodb_autoinc_lock_mode254 收藏
-
数据库 · MySQL | 5天前 | 连接池 · 高并发 · 故障排查 · MySQL教程 · 数据库运维 · mysql 高并发 连接池 max_connections Too many connections491 收藏
-
381 收藏
-
数据库 · MySQL | 6天前 | 性能优化 · InnoDB · 故障排查 · MySQL教程 · DBA实战 · mysql innodb 性能优化 预热 冷启动 MySQL 8.4 Buffer Pool158 收藏
-
数据库 · MySQL | 6天前 | binlog · 故障恢复 · 备份恢复 · MySQL教程 · DBA实战 · mysql DBA binlog 备份恢复 mysqlbinlog MySQL 8.4 PITR432 收藏
-
数据库 · MySQL | 6天前 | 字符集 · 故障排查 · MySQL教程 · 索引优化 · 排序规则 · mysql 排序规则 索引优化 utf8mb4 collation MySQL 8.4294 收藏
-
数据库 · MySQL | 6天前 | binlog · 主从复制 · 故障排查 · MySQL教程 · DBA实战 · mysql DBA binlog 主从复制 MySQL 8.4 复制延迟 relay log119 收藏
-
数据库 · MySQL | 6天前 | MySQL教程 · 慢查询治理 · 索引优化 · 分区表 · DBA实战 · mysql 分区表 慢查询 索引优化 MySQL 8.4 partition pruning133 收藏
-
数据库 · MySQL | 6天前 | 高并发 · 故障排查 · MySQL教程 · 事务隔离 · InnoDB锁 · mysql innodb 高并发 锁等待 MySQL 8.4 NOWAIT SKIP LOCKED439 收藏
-
291 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习