sql按月汇总销售数据需用group by提取“年份+月份”字段分组,配合sum()等聚合函数;各数据库提取方式不同但均需统一为“yyyy-mm”或“yyyymm”格式,并注意时区转换和null值过滤。

在 SQL 中用 GROUP BY 按月份汇总销售数据,关键是把日期字段提取出“年份+月份”作为分组依据,再配合聚合函数(如 SUM()、COUNT())计算指标。直接对完整日期分组会按天统计,必须先做时间截取。
提取年月作为分组字段
不同数据库提取年月的写法略有差异,核心是统一到“YYYY-MM”格式或数值型“YYYYMM”:
-
MySQL:使用
DATE_FORMAT(order_date, '%Y-%m')或YEAR(order_date)*100 + MONTH(order_date) -
PostgreSQL:用
TO_CHAR(order_date, 'YYYY-MM')或EXTRACT(YEAR FROM order_date)*100 + EXTRACT(MONTH FROM order_date) -
SQL Server:用
FORMAT(order_date, 'yyyy-MM')或YEAR(order_date)*100 + MONTH(order_date) -
SQLite:用
STRFTIME('%Y-%m', order_date)
基础按月汇总销售额示例
假设销售表叫 sales,含字段 order_date(日期)、amount(金额),以下为通用写法(以 MySQL 为例):
SELECT DATE_FORMAT(order_date, '%Y-%m') AS month, SUM(amount) AS total_sales, COUNT(*) AS order_count FROM sales WHERE order_date >= '2023-01-01' GROUP BY DATE_FORMAT(order_date, '%Y-%m') ORDER BY month;
这会返回每行一个自然月的总销售额和订单数,结果按月份升序排列。
注意时区与空值处理
真实业务中需防范两类常见问题:
- 如果
order_date是带时区的时间戳(如TIMESTAMP WITH TIME ZONE),先用AT TIME ZONE转为本地时区再提取月份,否则跨 midnight 的订单可能被分到错误月份 - 若存在
order_date IS NULL,默认会被归为同一组(NULL 组),建议加WHERE order_date IS NOT NULL显式过滤,避免干扰统计口径
扩展:按年月分组并补全缺失月份
GROUP BY 默认只返回有数据的月份。如需展示连续12个月(含零销售月份),不能单靠 GROUP BY,需构造月份维度表(如用递归 CTE 或日历表)再 LEFT JOIN 销售汇总结果。这是进阶需求,基础汇总无需此步。










