在日常工作中,经常需要从数据库里提取上个月的数据做报表或分析。比如财务月底对账、运营统计用户行为,这时候写一条准确又高效的 SQL 就特别关键。
基本思路
查上个月的数据,核心是构造一个时间范围:从上个月的第一天开始,到最后一天结束。假设你的表里有个日期字段 create_time,类型是 DATETIME 或 DATE,就可以用 MySQL 自带的时间函数来处理。
MySQL 示例
比如要查 user_log 表中上个月的所有记录:
SELECT * FROM user_log
WHERE create_time >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND create_time < DATE_FORMAT(CURDATE(), '%Y-%m-01');
这段语句的意思是:筛选出创建时间大于等于上个月第一天,且小于本月第一天的数据。这样就能精准命中整个上月。
更简洁的写法
也可以用 LAST_DAY 配合调整:
SELECT * FROM user_log
WHERE create_time >= DATE_SUB(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE())-1 DAY), INTERVAL 1 MONTH)
AND create_time <= LAST_DAY(DATE_SUB(CURDATE(), INTERVAL 1 MONTH));
这种写法先算出上个月最后一天,再结合起始日进行过滤,逻辑更直观一些。
注意时区和字段类型
如果 create_time 包含具体时间(如 2024-03-15 08:30:00),建议用 < 本月第一天的方式,避免漏掉最后一天的晚些数据。如果是纯日期类型,可以直接用 BETWEEN。
举个实际场景
比如你是个电商公司的运营,老板每周一都要看上周订单量,但系统只支持月度导出。你可以直接登录后台数据库,运行类似下面这条:
SELECT COUNT(*) AS order_count, SUM(amount) AS total_sales
FROM orders
WHERE order_date >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND order_date < DATE_FORMAT(CURDATE(), '%Y-%m-01')
AND status = 'completed';
马上就能拿到上个月完成订单的总数和销售额,省得手动翻页面一页页导出。
其他数据库变通
PostgreSQL 可以用 date_trunc('month', now() - interval '1 month'),SQLite 则常用 date('now','start of month','-1 month')。不同数据库语法略有差异,但思路一致:定位上个月的时间区间。
掌握这类查询,能让你在面对临时数据需求时快速响应,不用每次都求开发同事帮忙写脚本。