当前位置: 首页 > news >正文

MySQL 超出月份最大日期(工作总结)

前几天帮同事修改了一个bug,这个bug是怎么造成的呢。先来看需求,系统需要统计某个月份的数据。很简单的一个需求。 

同事的写的MySQL语句

SELECTREPLACE(FORMAT(sum(count_value),2), ',', '') as value,<if test="type == 'day'">count_date as `time`</if><if test="type == 'hour'">count_time as `time`</if><if test="type == 'month'">DATE_FORMAT(count_date, '%Y-%m') as `time`</if><if test="type == 'year'">DATE_FORMAT(count_date, '%Y') as `time`</if>FROMdevice_valueWHERE  count_date BETWEEN #{startTime} AND #{endTime}and node_id in<foreach collection="nodeIds" separator="," open="(" close=")" item="nodeId">#{nodeId}</foreach>GROUP BY<if test="type == 'day'">count_date</if><if test="type == 'hour'">count_time</if><if test="type == 'month'">DATE_FORMAT(count_date, '%Y-%m')</if><if test="type == 'year'">DATE_FORMAT(count_date, '%Y')</if><if test="type == 'day'">order by  count_date</if><if test="type == 'hour'">order by  count_time</if><if test="type == 'month'">order by  DATE_FORMAT(count_date, '%Y-%m')</if>

sql也很简单,就是通过传递不同的type从时间的不同角度去统计出device_value这张表中的在startTime和endTime这时间段内的value值之和。

然后就是Java代码了,具体就不展示了。总结来说他如果要查询六月的数据,他就是将前端传递过来的2024-06这样一个字符串拼接上一个01和31。然后就传递到xml中查询。运行时MySQL代码:

SELECT REPLACE( FORMAT( sum( count_value ), 2 ), ',', '' ) AS VALUE,count_date AS `time` 
FROMdevice_everyday_count_value 
WHEREcount_date BETWEEN '2024-06-01' AND '2024-06-31'AND node_id IN ( 'KTXTYCNH' ) 
GROUP BYcount_date 
ORDER BYcount_date

看一下查询结果

                        

你会发现是没有结果的,实际上6月是有数据的,但是6月确实没有31号的只有30号,我将他写的31改为30后再此运行同样MySQL代码结果如下

                                

讲到这里大家应该也发现了代码问题之处了,就是日常超出了范围导致的查询没有结果。在前端展示的时候并不会报错,只是小于31天的数据是没有值的。

最后我将他的Java代码在传递日期的时候给修改了,通过LocalTime来获取某一年的某一月的日期的开始以及结束日期。

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");LocalDate startTime = LocalDate.parse(date, formatter);String endDate = date;if("month".equals(dateType)){date = startTime.with(TemporalAdjusters.firstDayOfMonth()).toString();endDate = startTime.with(TemporalAdjusters.lastDayOfMonth()).toString();}else if("year".equals(dateType)){date = startTime.with(TemporalAdjusters.firstDayOfYear()).toString();endDate = startTime.with(TemporalAdjusters.lastDayOfYear()).toString();}
事后我有问过他,我问他当时怎么想的,为什么会当时会这样写代码呢?
他跟我说:我写的时候觉得没什么不对啊,我当时觉得每个月的月份开始日期都是01,然后结束最大就是31我拼接出来的日期就算是6月只有30天但是我31也没什么问题也包含了30号的日期,并不会遗漏数据所以就这么写了。
然后我又问他:你当时写的时候没去测一下这种写法在特殊的月份的时候查询会不会出现问题呢。
他说:我没有,我当时写来并没有调用接口的时候并没有报错,并且有数据我就没管了。
他当时写的时候是5月份所以并不会有什么问题。至此我也不好再多说什么

 我只能说善用现有的工具,别写魔法数字和魔法字符串。

路漫漫其修远兮,吾将上下而求索!!!

相关文章:

  • “脏读”、“幻读”、“不可重复读”
  • Nuxt3用pm2启动报错[PM2][ERROR] File ecosystem.config.js malformated
  • 数据分析必备:一步步教你如何用matplotlib做数据可视化(10)
  • 【Redis】Redis内存使用优化方法
  • 浙大宁波理工学院2024年成人高等继续教育招生简章
  • 搜狐视频全自动工具
  • 自动驾驶---Perception之视觉点云雷达点云
  • [保姆级教程]uniapp自定义导航栏
  • 【html】用html+css模拟Windows右击菜单
  • 【JS重点15】原型对象概述
  • C语言| 数组元素的删除
  • 四川汇聚荣科技有限公司靠谱吗?
  • 基于51单片机数字频率计的设计资料
  • Stable Diffusion初体验——基于机器学习通过神经网络的强大AI平台
  • 自制HTML5游戏《贪吃蛇》
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Golang-长连接-状态推送
  • JavaScript学习总结——原型
  • Java深入 - 深入理解Java集合
  • js正则,这点儿就够用了
  • NSTimer学习笔记
  • Rancher如何对接Ceph-RBD块存储
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Vue全家桶实现一个Web App
  • 关于 Cirru Editor 存储格式
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 技术发展面试
  • 跨域
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 数组大概知多少
  • 微信小程序开发问题汇总
  • 优秀架构师必须掌握的架构思维
  • Linux权限管理(week1_day5)--技术流ken
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 阿里云服务器购买完整流程
  • ​ArcGIS Pro 如何批量删除字段
  • ​力扣解法汇总946-验证栈序列
  • # Redis 入门到精通(七)-- redis 删除策略
  • #《AI中文版》V3 第 1 章 概述
  • #知识分享#笔记#学习方法
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (4)logging(日志模块)
  • (C语言)二分查找 超详细
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (苍穹外卖)day03菜品管理
  • (分布式缓存)Redis持久化
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (四)汇编语言——简单程序
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • .NET Core中的时区转换问题