在业务数据统计分析过程中,经常需要按照周或者季度维度对数据进行汇总,比如统计每周的用户新增量、每个季度的订单总金额等。这类需求的核心是通过SQL的日期函数将日期转换为对应的周或季度标识,再结合分组语句完成统计。

不同数据库的日期函数差异
不同关系型数据库的日期处理函数语法有所区别,下面先梳理主流数据库获取周和季度标识的常用函数。
MySQL数据库
MySQL提供了WEEK()函数获取日期所属的周数,QUARTER()函数获取日期所属的季度,使用方式如下:
-- 获取当前日期的周数,模式2表示周从周一开始,返回值为1-53 SELECT WEEK(NOW(), 2) AS week_num; -- 获取当前日期的季度,返回值为1-4 SELECT QUARTER(NOW()) AS quarter_num;
PostgreSQL数据库
PostgreSQL使用EXTRACT函数提取日期的周和季度信息,语法为EXTRACT(field FROM source):
-- 获取当前日期的周数,ISO周标准,返回值为1-53 SELECT EXTRACT(WEEK FROM NOW()) AS week_num; -- 获取当前日期的季度,返回值为1-4 SELECT EXTRACT(QUARTER FROM NOW()) AS quarter_num;
SQL Server数据库
SQL Server可以通过DATEPART函数获取周和季度信息:
-- 获取当前日期的周数,返回值为1-53 SELECT DATEPART(WEEK, GETDATE()) AS week_num; -- 获取当前日期的季度,返回值为1-4 SELECT DATEPART(QUARTER, GETDATE()) AS quarter_num;
按周统计业务数据示例
假设存在订单表order_info,表结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| order_id | INT | 订单ID |
| order_amount | DECIMAL(10,2) | 订单金额 |
| create_time | DATETIME | 订单创建时间 |
需求是统计2024年每一周的订单总金额,以MySQL为例,查询语句如下:
SELECT -- 拼接年和周数,作为周标识,方便区分不同年的同一周 CONCAT(YEAR(create_time), '-', LPAD(WEEK(create_time, 2), 2, '0')) AS week_label, SUM(order_amount) AS total_amount, COUNT(order_id) AS order_count FROM order_info WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01' GROUP BY YEAR(create_time), WEEK(create_time, 2) ORDER BY YEAR(create_time), WEEK(create_time, 2);
如果是PostgreSQL,对应查询语句调整为:
SELECT CONCAT(EXTRACT(YEAR FROM create_time), '-', LPAD(EXTRACT(WEEK FROM create_time)::TEXT, 2, '0')) AS week_label, SUM(order_amount) AS total_amount, COUNT(order_id) AS order_count FROM order_info WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01' GROUP BY EXTRACT(YEAR FROM create_time), EXTRACT(WEEK FROM create_time) ORDER BY EXTRACT(YEAR FROM create_time), EXTRACT(WEEK FROM create_time);
按季度统计业务数据示例
同样基于上面的order_info表,需求是统计2024年每个季度的订单总金额,MySQL实现如下:
SELECT -- 拼接年和季度,作为季度标识 CONCAT(YEAR(create_time), '-Q', QUARTER(create_time)) AS quarter_label, SUM(order_amount) AS total_amount, COUNT(order_id) AS order_count FROM order_info WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01' GROUP BY YEAR(create_time), QUARTER(create_time) ORDER BY YEAR(create_time), QUARTER(create_time);
SQL Server的实现语句如下:
SELECT CONCAT(YEAR(create_time), '-Q', DATEPART(QUARTER, create_time)) AS quarter_label, SUM(order_amount) AS total_amount, COUNT(order_id) AS order_count FROM order_info WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01' GROUP BY YEAR(create_time), DATEPART(QUARTER, create_time) ORDER BY YEAR(create_time), DATEPART(QUARTER, create_time);
注意事项
- 周数的计算模式需要根据业务规则选择,比如有的业务周从周日开始,有的从周一开始,不同模式会导致周数结果差异。
- 跨年的周处理需要注意,比如12月底的日期可能属于下一年的第一周,分组时要结合年份一起分组,避免出现不同年同一周的数据被合并的情况。
- 如果统计的时间范围跨度大,建议给
create_time字段添加索引,提升分组查询的效率。
实际使用中可以根据自身业务使用的数据库类型,选择对应的日期函数,调整查询语句即可满足按周或按季度的数据统计需求。