MySQL统计近7天(两周、一个月等)数据,没有数据显示为0

全屏阅读
  • 基本信息
  • 作者:
  • 作者已发布:973篇文章
  • 发布时间:2026年01月29日 17:02:49
  • 所属分类:Mysql优化, PHP+MySql
  • 阅读次数:29次阅读
  • 标签:

数据库

CREATE TABLE `sys_user` (
  `id` varchar(255) NOT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  `user_age` int DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;



INSERT INTO `sys_user` (`id`, `user_name`, `user_age`, `create_time`) VALUES ('1', '张三', NULL, '2022-05-14 09:51:49');


CREATE TABLE `test` (
  `id` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `test` (`id`) VALUES ('1');
INSERT INTO `test` (`id`) VALUES ('2');
INSERT INTO `test` (`id`) VALUES ('3');
INSERT INTO `test` (`id`) VALUES ('4');
INSERT INTO `test` (`id`) VALUES ('5');
INSERT INTO `test` (`id`) VALUES ('6');
INSERT INTO `test` (`id`) VALUES ('7');
INSERT INTO `test` (`id`) VALUES ('8');

方法一:

使用函数,创建一张临时表,并往里面加入查询范围内日期

DROP PROCEDURE IF EXISTS FillDateTable;

delimiter //
CREATE PROCEDURE FillDateTable(startTime varchar(20), endTime varchar(20))
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
  drop table if exists datetable;
  create TEMPORARY table datetable (dateNum datetime primary key, isweekday smallint);

  SET @x := date(startTime);
  REPEAT 
    insert into datetable (dateNum, isweekday) SELECT @x, case when dayofweek(@x) in (1,7) then 0 else 1 end;
    SET @x := date_add(@x, interval 1 day);
    UNTIL @x >= endTime END REPEAT;
END//
delimiter ;

CALL FillDateTable('2022-05-12', '2022-05-18');

-- 近7天
select
	DATE_FORMAT(dt.dateNum,'%Y-%m-%d') as date,
	IFNULL(table_user.num, 0) as num
from
	datetable dt
left join  (
	select DATE_FORMAT(su.create_time,'%Y-%m-%d') as createTime, COUNT(1) as num from sys_user su  
	where
		su.create_time BETWEEN DATE_SUB(CURDATE(),INTERVAL 7 DAY) AND DATE_SUB(CURDATE(),INTERVAL 1 DAY)
)table_user on dt.dateNum = table_user.createTime
 where
 	dt.dateNum BETWEEN DATE_SUB(CURDATE(),INTERVAL 7 DAY) AND DATE_SUB(CURDATE(),INTERVAL 1 DAY)
group by dt.dateNum

根据 FillDateTable(开始时间,结束时间),传入自己所要查询的日期范围。

查询结果

自动草稿

方法二:

获取近7天日期

SELECT @cdate := DATE_ADD(@cdate, INTERVAL 1 DAY) cdate
FROM
	(
		SELECT
			@cdate := DATE_SUB(CURDATE(), INTERVAL 8 DAY)
		FROM
			(
				SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
			) b
	) a

SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 生成一列7行的数据

注意:如果超过 7 天,查询 n 天的数据 ,那就要先生成一列 n 行的数据,可以使用其他有数据表代替(如下),最蠢的办法就是 union  

SELECT @cdate := DATE_ADD(@cdate, INTERVAL 1 DAY) cdate
FROM
	(
		SELECT
			@cdate := DATE_SUB(CURDATE(), INTERVAL 8 DAY)
		FROM
			(
				SELECT * FROM test limit 7 
			) b
	) a

注意:必须保证参照表有大于或等于索要查询天数的数据量

-- union 方式
SELECT
	table_date.cdate,
	IFNULL(table_user.num, 0) nums
FROM
(
	SELECT
		 @cdate := DATE_ADD(@cdate, INTERVAL 1 DAY) cdate
		FROM
		 (
			SELECT
			 @cdate := DATE_SUB(CURDATE(), INTERVAL 8 DAY)
			FROM
			 	(
				SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
             	) b
			) a
) table_date
LEFT JOIN 
 (
    select DATE_FORMAT(su.create_time,'%Y-%m-%d') createTime, COUNT(su.id) num from sys_user su
 		where DATE_FORMAT(su.create_time,'%Y-%m-%d') BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) and  DATE_SUB(CURDATE(), INTERVAL 1 DAY)
 ) table_user  ON table_date.cdate = table_user.createTime
 WHERE
 	-- 不加也行,上面已经是取7天的数据
 	table_date.cdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND DATE_SUB(CURDATE(), INTERVAL 1 DAY)
GROUP BY table_date.cdate;


-- 参照表 方式
SELECT
	table_date.cdate,
	IFNULL(table_user.num, 0) nums
FROM
(
	SELECT
		 @cdate := DATE_ADD(@cdate, INTERVAL 1 DAY) cdate
		FROM
		 (
			SELECT
			 @cdate := DATE_SUB(CURDATE(), INTERVAL 8 DAY)
			FROM
			 	(
				SELECT * FROM test limit 7 
             	) b
			) a
) table_date
LEFT JOIN 
 (
    select DATE_FORMAT(su.create_time,'%Y-%m-%d') createTime, COUNT(su.id) num from sys_user su
 		where DATE_FORMAT(su.create_time,'%Y-%m-%d') BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) and  DATE_SUB(CURDATE(), INTERVAL 1 DAY)
 ) table_user  ON table_date.cdate = table_user.createTime
 WHERE
 	-- 不加也行,上面已经是取7天的数据
 	table_date.cdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND DATE_SUB(CURDATE(), INTERVAL 1 DAY)
GROUP BY table_date.cdate;

查询结果

自动草稿

部分筛选条件

-- 获取上个月
DATE_FORMAT(su.create_time,'%Y-%m') =  DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -1 month),'%Y-%m')

-- 获取本月截止到昨天
DATE_FORMAT(su.create_time,'%Y-%m-%d') BETWEEN concat(DATE_FORMAT(now(),'%Y-%m'), '-01') AND  DATE_FORMAT( DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%Y-%m-%d')

-- 获取今年截至到昨天
DATE_FORMAT(su.create_time,'%Y-%m-%d') BETWEEN concat(DATE_FORMAT(now(),'%Y'), '-01-01') AND  DATE_FORMAT( DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%Y-%m-%d')

-- 获取近7天
su.create_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND DATE_SUB(CURDATE(), INTERVAL 1 DAY)

顶一下
(0)
100%
订阅 回复
踩一下
(0)
100%
» 郑重声明:本文由mpxq168发布,所有内容仅代表个人观点。版权归恒富网mpxq168共有,欢迎转载, 但未经作者同意必须保留此段声明,并给出文章连接,否则保留追究法律责任的权利! 如果本文侵犯了您的权益,请留言。

目前有 0 条留言 其中:访客:0 条, 博主:0 条

给我留言

您必须 [ 登录 ] 才能发表留言!