必须用case when先将年龄映射为区间标签再group by,否则报错;常见错误是漏写else导致null年龄用户被丢弃;正确写法需覆盖全范围并明确else分支。

用 CASE WHEN 实现年龄区间分组
直接在 GROUP BY 里写区间判断会报错,必须先用 CASE WHEN 把年龄映射成区间标签,再分组。常见错误是漏写 ELSE,导致 NULL 年龄用户被丢弃。
CASE WHEN age >= 0 AND ageWHEN age >= 18 AND ageWHEN age >= 35 AND age-
ELSE '老年'—— 必须加,否则age为NULL或负数时整行不参与统计
WHERE 过滤要放在 GROUP BY 前
如果只想统计“已验证手机号”的用户,WHERE phone_verified = 1 必须写在 GROUP BY 之前。写在 HAVING 里会先分组再过滤,结果不准——比如某组只有 1 个用户但没验证,HAVING 会整个删掉这组,而不是跳过该用户。
正确顺序:SELECT ... FROM users WHERE phone_verified = 1 GROUP BY ...
注意年龄字段类型和空值处理
很多表里 age 是 INT 但允许 NULL,或者存的是出生日期(BIRTH_DATE),这时不能直接用 age 分组。
- 若字段是日期型,得先算年龄:
TIMESTAMPDIFF(YEAR, BIRTH_DATE, CURDATE())(MySQL)或EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date))(PostgreSQL) - 若
age为NULL,CASE WHEN默认不匹配任何分支,必须靠ELSE捕获 - 避免用
ROUND(age)或CAST(age AS SIGNED)强转——原始数据有小数或字符串时会出错
性能敏感场景建议加函数索引
当表很大、且频繁按年龄区间查询时,CASE WHEN 无法走索引。可行办法是新增一个计算列并建索引:
ALTER TABLE users ADD COLUMN age_group VARCHAR(10)
GENERATED ALWAYS AS (
CASE
WHEN age >= 0 AND age = 18 AND age = 35 AND age
<p>然后对 <code>age_group</code> 建索引:<code>CREATE INDEX idx_age_group ON users(age_group);</code></p>
<p>注意:PostgreSQL 不支持生成列,得用表达式索引;SQLite 不支持函数索引,只能靠应用层缓存或预计算。</p>











