MySQL 8.0.29+ 支持 HISTOGRAM 函数,但仅限单列全局统计,不支持 GROUP BY;分组直方图需用 WIDTH_BUCKET(PostgreSQL/Oracle/DuckDB)或 CASE WHEN(MySQL)手动分桶,或导出数据用 Pandas 可视化。

用 HISTOGRAM 函数直接生成分组直方图(MySQL 8.0.29+)
MySQL 8.0.29 起原生支持 HISTOGRAM,但注意:它不支持按部门分组后各自画直方图,只能对单列全局统计。所以如果你执行:
SELECT DEPARTMENT, HISTOGRAM(EMPLOYEE_SALARY) FROM EMPLOYEES GROUP BY DEPARTMENT;会报错
ERROR 3612 (HY000): Histograms are not supported for grouped queries。这不是写法问题,是语法限制——HISTOGRAM 本身不接受 GROUP BY。
手动模拟直方图:用 WIDTH_BUCKET + GROUP BY(PostgreSQL / Oracle / DuckDB)
主流支持窗口函数的数据库可用 WIDTH_BUCKET 把薪资划入预设区间,再按部门和桶编号聚合计数。关键点在于桶边界必须对齐,否则跨部门比较失真:
- 先查出全公司薪资范围:
SELECT MIN(SALARY), MAX(SALARY) FROM EMPLOYEES,比如得到5000和35000 - 定 6 个桶(即 5 等分区间),宽度 =
(35000 - 5000) / 5 = 6000 - 计算桶号:
WIDTH_BUCKET(SALARY, 5000, 35000, 5),返回 1~6 - 最终查询:
SELECT DEPARTMENT, WIDTH_BUCKET(SALARY, 5000, 35000, 5) AS BUCKET, COUNT(*) AS COUNT FROM EMPLOYEES GROUP BY DEPARTMENT, BUCKET ORDER BY DEPARTMENT, BUCKET;
注意:PostgreSQL 的 WIDTH_BUCKET 下界包含、上界不包含;Oracle 行为一致;DuckDB 也兼容。但 SQLite 和旧版 MySQL 没这函数,得换方案。
MySQL 兼容方案:用 CASE WHEN 手动分桶
在没有 WIDTH_BUCKET 的 MySQL(包括 8.0 大部分版本)中,唯一可靠方式是显式定义薪资区间。缺点是硬编码、难复用,但胜在可控:
- 区间必须互斥且覆盖全集,例如:
CASE WHEN SALARY < 10000 THEN 'A: <10K' WHEN SALARY < 20000 THEN 'B: 10K-20K' WHEN SALARY < 30000 THEN 'C: 20K-30K' ELSE 'D: ≥30K' END AS SALARY_RANGE
- 嵌套进查询:
SELECT DEPARTMENT, CASE ... END AS SALARY_RANGE, COUNT(*) AS FREQUENCY FROM EMPLOYEES GROUP BY DEPARTMENT, SALARY_RANGE ORDER BY DEPARTMENT, FIELD(SALARY_RANGE, 'A: <10K', 'B: 10K-20K', 'C: 20K-30K', 'D: ≥30K'); - 别用
ORDER BY SALARY_RANGE—— 字符串排序会让 'A' 'B' 'C' 'D' 乱序,FIELD()是 MySQL 特有保序手段
导出数据后用 Python/Pandas 画图更实际
SQL 本质是关系代数引擎,不是可视化工具。即使你拼出带桶号和频次的结果,离“直方图”还差坐标轴、颜色、标签三步。真正省事的做法是把分组聚合结果导出,交给 Pandas:
- SQL 只负责干净分组:
SELECT DEPARTMENT, SALARY FROM EMPLOYEES;
- Pandas 中按部门分组、各自调
df.hist(bins=10)或sns.histplot(data=df, x='SALARY', hue='DEPARTMENT') - 这样能自动适配不同部门的数据分布形态(比如销售部薪资方差大、研发部集中在中高位),SQL 硬分桶反而会掩盖这种差异
最常被忽略的一点:直方图的“桶宽”在不同部门间是否该统一?如果强制统一(如都用 5000 宽度),可能让小部门每个桶只有 1–2 人,噪声极大;而放任各部自适应,又无法横向对比。这个权衡不在 SQL 层解决,而在分析目标里明确——你要的是部门内部分布特征,还是跨部门薪资结构对标。


















