在业务数据分析中,经常需要统计不同年龄段的用户数量、消费金额等指标,SQL提供了多种实现按年龄段分组统计的方法,其中FLOOR函数和CASE区间判断是最常用的两种方案。

基于FLOOR函数的年龄段分组实现
FLOOR函数的作用是返回小于或等于指定数值的最大整数,我们可以利用这个特性,将年龄除以区间步长后取FLOOR值,再乘以步长得到区间起始值,从而实现等宽年龄段的划分。
实现原理
假设我们要按10岁为一个区间进行分组,年龄30岁除以10得到3,FLOOR(3)为3,乘以10得到30,对应30-39岁区间;年龄25岁除以10得到2.5,FLOOR(2.5)为2,乘以10得到20,对应20-29岁区间,以此类推。
代码示例
假设存在用户表user_info,包含user_id和age字段,统计各10岁区间的用户数量:
-- 按10岁为区间统计用户数量
SELECT
FLOOR(age / 10) * 10 AS age_group_start,
CONCAT(FLOOR(age / 10) * 10, '-', FLOOR(age / 10) * 10 + 9) AS age_group,
COUNT(user_id) AS user_count
FROM user_info
WHERE age IS NOT NULL
GROUP BY FLOOR(age / 10) * 10
ORDER BY age_group_start;
如果需要调整区间步长,只需要修改除法中的数值即可,比如按5岁为区间,将age / 10改为age / 5即可。
基于CASE区间判断的年龄段分组实现
当年龄区间不是等宽,或者需要自定义特殊区间时,FLOOR函数就不再适用,此时可以使用CASE条件判断语句来定义每个年龄段的划分规则。
实现原理
CASE语句会按顺序判断每个条件,当某个条件满足时返回对应的结果,我们可以为每个年龄段定义对应的条件,比如小于18岁为未成年,18到35岁为青年等。
代码示例
同样基于user_info表,统计自定义年龄段的用户数量:
-- 自定义年龄段统计用户数量
SELECT
CASE
WHEN age < 18 THEN '未成年'
WHEN age BETWEEN 18 AND 35 THEN '青年'
WHEN age BETWEEN 36 AND 59 THEN '中年'
ELSE '老年'
END AS age_group,
COUNT(user_id) AS user_count
FROM user_info
WHERE age IS NOT NULL
GROUP BY
CASE
WHEN age < 18 THEN '未成年'
WHEN age BETWEEN 18 AND 35 THEN '青年'
WHEN age BETWEEN 36 AND 59 THEN '中年'
ELSE '老年'
END
ORDER BY
CASE
WHEN age < 18 THEN 1
WHEN age BETWEEN 18 AND 35 THEN 2
WHEN age BETWEEN 36 AND 59 THEN 3
ELSE 4
END;
这里GROUP BY和ORDER BY中都需要重复CASE逻辑,部分数据库支持给CASE结果起别名后在GROUP BY和ORDER BY中使用别名,比如MySQL可以直接使用GROUP BY age_group。
两种方式的对比与选择
| 对比维度 | FLOOR函数方案 | CASE区间判断方案 |
|---|---|---|
| 适用场景 | 等宽年龄段,区间规则统一 | 自定义非等宽区间,特殊规则分组 |
| 代码简洁度 | 高,只需简单计算 | 低,需要重复书写条件逻辑 |
| 灵活性 | 低,只能按固定步长划分 | 高,可自由定义任意区间规则 |
| 可维护性 | 高,修改步长只需改一个数值 | 低,修改区间需要调整多个条件 |
如果业务需求是按固定步长的等宽区间分组,优先选择FLOOR函数方案,代码更简洁维护成本更低;如果需要自定义不规则的年龄段,比如电商场景中按0-17岁、18-24岁、25-34岁等运营定义的区间统计,就选择CASE区间判断方案。
注意事项
- 分组前需要过滤掉年龄为NULL的记录,避免NULL值被分到单独的组影响统计结果
- 使用FLOOR函数时,要注意年龄字段的数据类型,如果是字符串类型需要先转换为数值类型
- CASE语句的条件判断顺序很重要,应该按照区间从小到大的顺序书写,避免条件覆盖
- 如果年龄超过100岁,FLOOR函数方案会自动生成100+的区间,CASE方案需要在ELSE分支中定义对应的区间名称
实际业务中可以结合两种方式的优点,对于大部分等宽区间用FLOOR计算,特殊区间再用CASE补充调整,提升统计逻辑的灵活性和简洁性。