首页 > 数据库 >一行SQL语句实现统计未来7天、按月统计数据,无数据填充0

一行SQL语句实现统计未来7天、按月统计数据,无数据填充0

时间:2024-05-08 11:11:27浏览次数:14  
标签:语句 -% help 填充 INTERVAL topic CURDATE SQL DAY

1 背景

  由于业务需求,在项目的报表中心中需要未来7天、按月统计数据,且要求按天补全数据,补数据填为0。
  附实测SQL语句,请大家指正。

2 举例

2.1未来7天,按天补全数据,无数据填充0

sql语句:

select t1.lastDays as x, IFNULL(t2.count,0) as val
from (SELECT date_format( @lastDay := date_add( @lastDay, INTERVAL 1 DAY ), '%Y-%m-%d' ) lastDays 
      FROM ( SELECT @lastDay := date_add( curdate( ), INTERVAL - 1 DAY ) FROM mysql.help_topic LIMIT 7 ) a)as t1
left join (select DATE_FORMAT(maintenance_time, '%Y-%m-%d') as time_1, SUM(b.employee_number) as count 
	from maintenance_plan a 
	LEFT JOIN maintenance_strategy b ON (b.model_id = a.model_id) 
	where a.maintenance_type=1 group by maintenance_time)t2 on t2.time_1=t1.lastDays

查询结果:

 
2.2 当月1-月底,按天补全数据,无数据填充0
sql语句:
select t1.lastDays as x, IFNULL(t2.count,0) as val
from (SELECT date_format(date_add(@firstDayOfMonth := DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01'), INTERVAL a.help_topic_id DAY), '%Y-%m-%d') AS lastDays  
      FROM mysql.help_topic a 
	  WHERE a.help_topic_id BETWEEN 0 AND DATEDIFF(@lastDayOfMonth := LAST_DAY(CURDATE()), @firstDayOfMonth := DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01')))as t1
left join (select DATE_FORMAT(maintenance_time, '%Y-%m-%d') as time_1, COUNT(x.id) as count from maintenance_plan x group by DATE_FORMAT(x.maintenance_time, '%Y-%m-%d'))t2 on t2.time_1=t1.lastDays	

查询结果:还有2024-05-01和2024-05-02

 

3 SQL语句原理和拆解说明

原理:使用MySql的系统表help_topic,使用表中自增ID(help_topic_id),用于进行行表关联操作和计数。
  使用sql语句查询,发现help_topic累计有701条数据(包括help_topic_id=0),MySql版本为:8.0.27

3.1 拆解思路

3.1.1 第一步:通过help_topic取连续的数值段

查询未来7天SQL语句,如下:

SELECT date_format( @lastDay := date_add( @lastDay, INTERVAL 1 DAY ), '%Y-%m-%d' ) lastDays
FROM ( SELECT @lastDay := date_add( curdate( ), INTERVAL - 1 DAY ) FROM mysql.help_topic LIMIT 7 ) a

date_add( @lastDay, INTERVAL 1 DAY ) 表示每次增加1天,

date_add( curdate( ), INTERVAL - 1 DAY ) 表示包括当天

LIMIT 7 表示取7条记录

执行结果:

 

 查询当月每天SQL语句,如下:

SELECT date_format(date_add(@firstDayOfMonth := DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01'), INTERVAL a.help_topic_id DAY), '%Y-%m-%d') AS lastDays 
FROM mysql.help_topic a 
WHERE a.help_topic_id BETWEEN 0 AND DATEDIFF(@lastDayOfMonth := LAST_DAY(CURDATE()), @firstDayOfMonth := DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01'))
DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01') 表示取当月的1号
LAST_DAY(CURDATE()) 表示当前日期的当月最后一天

执行结果:

 

3.1.2 第二步:使用left join左连接业务表

        有了第一步的日期字段,结合业务表时,需要使用left join进行左连接。

        使用on,将业务表中日期字段格式化为%Y-%m-%d,与日期字段(lastDays)格式保持一致,并将统计的结果值命名为指定的字段名(count),用于使用别名t2.count取值。如下所示

select t1.lastDays as x, IFNULL(t2.count,0) as val
from (SELECT date_format(date_add(@firstDayOfMonth := DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01'), INTERVAL a.help_topic_id DAY), '%Y-%m-%d') AS lastDays  
      FROM mysql.help_topic a 
	  WHERE a.help_topic_id BETWEEN 0 AND DATEDIFF(@lastDayOfMonth := LAST_DAY(CURDATE()), @firstDayOfMonth := DATE_FORMAT(CURDATE() - INTERVAL (DAY(CURDATE()) - 1) DAY, '%Y-%m-01')))as t1
left join (select DATE_FORMAT(maintenance_time, '%Y-%m-%d') as time_1, COUNT(x.id) as count from maintenance_plan x group by DATE_FORMAT(x.maintenance_time, '%Y-%m-%d'))t2 on t2.time_1=t1.lastDays	

 

3.1.3 第三步:查询数据时,使用IFNULL校验数据值,当为NULL时,赋值为0

        如果业务表中无该日期的数据,left join业务表中该日期的记录为null,故可以在查询结果中使用IFNULL校验t2.count,当统计天无数据时赋值为0。

 

4 拓展

统计未来7个月,将DAY换成MONTH,例子如下:

 

标签:语句,-%,help,填充,INTERVAL,topic,CURDATE,SQL,DAY
From: https://www.cnblogs.com/guobm/p/18179234

相关文章

  • SQL Server实战五:存储过程与触发器
      本文介绍基于MicrosoftSQLServer软件,实现数据库存储过程与触发器的创建、执行、修改与删除等操作。目录1交互式创建并执行——存储过程一2交互式创建并执行——存储过程二3用T-SQL创建——存储过程一4用T-SQL创建——存储过程二5交互式修改存储过程6用T-SQL修改存储......
  • 报错sql_mode=only_full_group_by
    这个问题的原因是,在这种模式下,sql分组时默认只能select+分组字段以及聚合函数,相当于做一个规范检查但很多时候并不需要这个检查,因为真实sql中,分组后很多字段是1对1的,比如分组id,那么其他字段都可以查出来才对这是可以修改一下这种配置,基本上有三种方式:1、修改sql的配置文件......
  • 如何分析慢SQL语句
    如果一条sql执行很慢的话,通常会使用MySQL自动的执行计划explain来去查看这条sql的执行情况,比如在这里面可以通过key和key_len检查是否命中了索引,如果本身已经添加了索引,也可以判断索引是否有失效的情况,第二个,可以通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全......
  • GreatSQL的sp中添加新的sp_instr引入的bug解析
    GreatSQL的sp中添加新的sp_instr引入的bug解析一、问题发现在一次开发中用到的sp需要添加新的sp_instr以满足需求,但是添加了数个sp_instr以后发现执行新的sp会发生core。注:本次使用的GreatSQL8.0.32-251、sp_head.cc的init_sp_psi_keys()代码里面添加10个新的sp_instr:void......
  • postgresql中视图建立,字段拼接,同一个表的多行之间的多个字段相减
    首先表是这样的CREATETABLEpublic.tb_realtime_data( s_idvarchar(48)NOTNULL, sensor_namevarchar(48)NULL, sensor_index_codevarchar(48)NULL, sensor_valuenumeric(20,10)NULL, statistics_statusint4NULL, alarm_timetimestampNOTNULL, create_time......
  • Oracle update语句引起大量业务卡顿
    记一次update语句引起大量业务卡顿分析处理过程,聊聊我的思路。技术人人都可以磨炼,但处理问题的思路和角度各有不同,希望这篇文章可以抛砖引玉。以一个例子为切入点一、问题背景某业务模块反馈最近出现过几次业务卡顿,数据库中定位到有几个insertinto语句的gc等待比较严重,虽然......
  • Mysql脚本——备份客户自建数据库
    #!/bin/bashDATE=$(date+%F_%H-%M-%S)HOST=127.0.0.1USER=rootPASS=Linux@123PORT=3306BACKUP_DIR=./db_backup#删选客户自建数据库(排除系统库)DB_LIST=$(mysql-u$USER-p$PASS-h$HOST-P$PORT-s-e"showdatabases;"2>/dev/null|egrep-v"Database|......
  • mysql死锁优化
    查看连接showprocesslist--已开启10秒以上的活跃连接SELECTid,user,db,command,state,time,infoFROMinformation_schema.processlistwherecommand<>'sleep'andtime>10orderbytime;--已运行超过10s的执行计划SELECTid,user,db,command,state,timeFROMinfo......
  • 多语言 JDBC SQL 发送
    多语言JDBCSQL发送记录各个语言使用JDBC发送SQL的代码片段。Pythonimportjaydebeapi#pipinstalljaydebeapi#JDBC驱动类名driver='com.mysql.jdbc.Driver'#数据库连接URLurl='jdbc:mysql://hostname:port/databasename?characterEncoding=UTF-8&serverT......
  • Glang&Mysql&Excel
    packagemainimport( "database/sql" "fmt" "log" _"github.com/go-sql-driver/mysql" "github.com/tealeg/xlsx")funcmain(){ //连接MySQL数据库 db,err:=sql.Open("mysql","root:123456......