数据库按日、周、月、年查询date_format日期相关操作以及时区转化convert_tz,时间差timestampdiff等

369 阅读3分钟

在使用统计之类的功能,难免会碰到按照日期归并的操作,例如:按天查询归并、按月查询归并;又或者需要计算时间差,然后求和等,下面简单介绍一下他们使用

ps:数据库查询语句本身不区分大小写,不必拘泥于大小写问题,喜欢小写就小写,喜欢大写就大写就行

时间格式化date_format/时区转化convert_tz

假设下面我们需要对某一个记录表(record)让其按天归并计算器,直接使用 date_format 函数格式化,这样就会按照格式化的日期,进行按天归并

ps: %Y-每年,%m-每月(大写是英文),%d-天,%a-周

select date_format(created_time, "%Y-%m-%d-%a") as day, cast(count(*) AS CHAR) as count
from record
where created_time between ${start} and ${end}
group by day

以为按照上面处理就完事了么,不并没有,其会出现一个格式化的时区问题(众所周知,时间会又一个时区问题,那这个时区出现问题的点就在时间格式化上,毕竟通用的时间肯定是以零时区为基准参考的),一般服务器都是零时区(那么就会格式化成0时区的结果,就不符合预期了),如果需要,可以将数据库所在服务器设置成自己的时区,也没问题

我们也可以通过 convert_tz 函数 给我们的时间转化为某个时区 convert_tz(时间参数,原时区,转化时区)

//如这个所示
convert_tz(created_time, "+00:00", "+08:00")
//也会出现固定的标识,这也是一个意思,都是代表某个地方的时区
convert_tz(created_time, "UTC", "US/EASTERN")

下面转化一下我们的时间参数改进一下即可

select date_format(convert_tz(created_time, "+00:00", "+08:00"), "%Y-%m-%d-%a") as day, cast(count(*) AS CHAR) as count
from record
where created_time between ${start} and ${end}
group by day

时间差timestampdiff/datediff

有时,我们我们也会碰到时间区间计算总值问题,例如:我们对某个请假记录表统计,统计每个人这一年的的请假总时长,那么就会用到这个功能

基础使用方式datediff、timestampdiff

//结果取天,结束时间-开始时间
datediff(end_date, start_date)

//时间戳方式,结果自定义,第一个为转化类型minute、hour、day等
//参数为单位-开始时间-结束时间
timestampdiff(hour, start_datetime, end_datetime)

按照上面案例使用即可,我们写一条简易 sql 语句,实现该功能,统计某一段时间内,每个人的请假总时间(单位:小时)

SELECT timestampdiff(hour, start_time, end_time) AS totalTime, user.name as name, record.user_id as id
from record
left join user on record.user_id = user.id
where create_time between 查询开始时间 and 查询结束时间
group by id

最后

一些统计操作还是占用数据库时间还是挺久的,对于很多有优化的项目可能用不到这些,有些涉及关联比较多的,会直接筛选出来字段,然后分别根据筛选出来的字段分批次定向查询,然后在服务器端边统计边查询,最后合并成想要的数据,这样能够大幅度减少数据库统计的占用时间(一些涉及关联表数据比较多的可能会从 O(m*n)变成 O(m+n)),当然是对于重服务器轻数据库的情况

实际根据自己情况来,假如做外包,可能根本不在意这些,时间是最宝贵的,直接一把撸就完事了,优化是优化的钱,对于一些需要打磨的产品,还是要有一些思考在里面的