mysql按日、时统计,空值填充0

需求

mysql按日、时统计时,单纯用group by会出现空值,故需要新建一个时间序列,再通过左连的形式来统计
如下

在这里插入图片描述

实现

1、利用mysql.help_topic表

select @a:=@a + 1 AS `index`, DATE_FORMAT(ADDDATE( "2023-03-01 15:23:18" ,INTERVAL @a DAY),'%Y-%m-%d') AS date FROM mysql.help_topic,(SELECT @a:=0) temp LIMIT 30

这是一条MySQL的SQL语句,它用来生成一个日期序列,包括从"2023-03-01"开始的连续的30天日期。下面是语句的详细解释:
首先,定义一个变量@a并将其初始化为0,这样就可以在后续的生成日期序列中使用。
然后,将mysql.help_topic表与子查询(SELECT @a:=0) temp连接起来,连接条件是没有连接条件,(这里目的是让子查询只执行一次,并且返回一行数据,初始化@a变量)。
接下来就是生成日期序列的逻辑:使用DATE_FORMAT函数将以@a为天数增量的日期计算出来,并将其格式化为'%Y-%m-%d'的日期字符串表示。这里ADDDATE函数将"2023-03-01 15:23:18"增加了@a天,然后通过DATE_FORMAT函数将其格式化为"%Y-%m-%d"的日期字符串表示。
最后,为了控制日期序列的长度,使用LIMIT语句限制了返回结果的数量,这里是30个日期。
最终,通过这条SQL语句,可以生成一个长度为30的日期序列,并将其作为结果集返回,其中列名为index,表示日期序列中日期的顺序,另一列为date,表示按格式化后的日期字符串表示的日期值。

-- 结果
1	2023-03-02
2	2023-03-03
3	2023-03-04
4	2023-03-05
5	2023-03-06
6	2023-03-07
7	2023-03-08
...

-- 设备历史数量查询-日
SELECT date_format(c.date, '%c月%e日') AS date, IFNULL(c.count,0) AS count 
FROM ( 
SELECT * FROM 
( select @a:=@a + 1 AS `index`, DATE_FORMAT(ADDDATE( "2023-03-01 15:23:18" ,INTERVAL @a DAY),'%Y-%m-%d') AS date FROM mysql.help_topic,(SELECT @a:=0) temp LIMIT 30 ) 
AS t1 LEFT JOIN (
SELECT date_format(td.created, '%Y-%m-%d') AS dateDay, count(*) as count FROM t_device td WHERE td.created > "2023-03-01 15:23:18" AND td.created < "2023-03-31 15:23:18" and td.is_delete=0 group by date_format(td.created, '%Y-%m-%d') )
AS t2 ON t1.date = t2.dateDay) AS c ORDER BY date_format(c.date, '%Y-%m-%d') asc

-- 结果
320
330
340
350
360
370
380
390
3100
3110
3120
3130
3140
3150
3160
3170
3180
3190
3200
3210
3220
3230
3240
3250
3260
3270
3280
3291
3307
3312

2、利用union

SELECT @xi:=@xi+1 as `index` from
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc1,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc2,
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc3,
(SELECT @xi:=0) xc0

这是一条MySQL的SQL语句,目的是生成包含1~125的自然数序列。下面是该语句的详细解释:
首先,定义变量@xi并将其初始化为0,这样就可以在后续的生成数字序列中使用。
然后,将五个SELECT语句的结果集连接在一起,从而得到一个包含125个记录的虚拟表。这里使用了笛卡尔积的方法,将多个SELECT语句的结果集进行连接。
最后,通过SELECT子句在每个记录上执行算术运算(@xi:=@xi+1),将@xi变量的值递增1,并将其作为一个新的列添加到结果集中,以此生成包含1~125的自然数序列。
最终,通过这条SQL语句,可以生成一个包含1~125的自然数序列,并将其作为结果集返回,其中列名为index,表示数字序列中数字的顺序。

其中
(SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc2 需要多少个就写多少个,日期统计比较少的话,比较适合
-- 结果 
1
2
3
4
5
6
7
...

最终sql

SELECT date_format(c.date, '%c月%e日') AS date, IFNULL(c.count,0) AS count 
FROM ( 
SELECT * FROM 
(
SELECT `index`,DATE_FORMAT(ADDDATE( "2023-03-22 15:23:18" ,INTERVAL `index` DAY),'%Y-%m-%d') as date
FROM ( 
 SELECT @xi:=@xi+1 as `index` from 
 (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc1, 
 (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc2, 
 (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) xc3,   
 (SELECT @xi:=0) xc0 
) xcxc LIMIT 30 
) 
AS t1 LEFT JOIN (
SELECT date_format(td.active_time, '%Y-%m-%d') AS dateDay, count(*) as count FROM t_device td WHERE td.active_time > "2023-03-22 15:23:18" AND td.active_time < "2023-04-21 15:23:18" and td.is_delete=0 and td.on_line!=0 group by date_format(td.active_time, '%Y-%m-%d') )
AS t2 ON t1.date = t2.dateDay) AS c ORDER BY date_format(c.date, '%Y-%m-%d') asc


-- 结果
3230
3240
3250
3260
3270
32810
3290
3300
3314
410
420
430
440
450
465
470
480
490
4100
4110
4120
4131
4140
4150
4160
4170
4180
4190
4200
4210
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值