如何使用MySQL存储过程统计表中最近7天记录并区分打印状态
如何用MySQL存储过程统计最近7天的已打印/未打印记录
先说说你原存储过程里的几个问题:
- 日期条件逻辑错误:你写的
date((curdate() - 7)) and date(curdate())没有关联表中的日期字段,相当于没加有效的日期筛选,而且这种写法也没法正确限定最近7天的范围 - 不必要的
GROUP BY:你要的是符合条件的总记录数,不是按日期分组统计,加了GROUP BY会导致没有匹配记录时返回NULL,而不是预期的0 - 未处理空结果场景:如果某类记录(比如已打印)不存在,原代码会把输出参数设为
NULL,这可能不符合业务需求
下面是修正并优化后的存储过程:
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_printnotprintdailyexpenses`( IN i_localBodyId VARCHAR(10), IN i_epId INT(20), OUT printed INT(20), OUT notprinted INT(20) ) BEGIN -- 统计最近7天内已打印的记录数,无匹配时返回0 SELECT COALESCE(COUNT(*), 0) INTO printed FROM tbl_dailyExpenses WHERE -- 替换成你表中实际的日期字段(比如expense_date) DATE(expense_date) BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE() AND localBodyId = i_localBodyId AND epId = i_epId AND isPrinted = 1; -- 统计最近7天内未打印的记录数,无匹配时返回0 SELECT COALESCE(COUNT(*), 0) INTO notprinted FROM tbl_dailyExpenses WHERE DATE(expense_date) BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE() AND localBodyId = i_localBodyId AND epId = i_epId AND isPrinted = 0; END
关键优化点说明:
- 正确的日期范围筛选:用
DATE_SUB(CURDATE(), INTERVAL 7 DAY)计算7天前的日期,搭配CURDATE()限定最近7天的范围。注意要把expense_date替换成你表中实际存储记录日期的字段名 - 处理空结果:
COALESCE(COUNT(*), 0)确保当没有符合条件的记录时,输出参数会被设为0,而不是NULL - 移除冗余分组:去掉了不必要的
GROUP BY,直接统计总数,逻辑更清晰 - 更直观的赋值方式:用
SELECT ... INTO直接把统计结果赋值给输出参数,比SET写法更可靠
如果你的日期字段是带时间的datetime类型,为了让查询能用到字段索引(提升性能),可以把日期条件改成这样:
expense_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND expense_date < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
这种写法避免了对字段使用DATE()函数,能触发索引扫描,查询效率更高。
内容的提问来源于stack exchange,提问作者Laxmikant Tanpure
相关产品推荐
相关产品推荐

