
本文详解如何将数据库查询返回的透视表格式 json 数据(含月份与多厂商数值)转换为 highcharts 堆叠柱状图,涵盖数据结构映射、配置关键项(如 stacking: 'normal')及完整可运行示例。
在实际业务报表开发中,常需将后端返回的「宽表」格式数据(如 SQL PIVOT 结果)可视化为堆叠柱状图:X 轴为时间维度(如月份),每个柱子按厂商(AUTOLIV、Continental 等)分层堆叠,高度代表对应数值。Highcharts 本身不直接接受宽表结构,需将原始数据转置(pivot → transpose)为 Highcharts 所需的 series 数组格式——即每个厂商作为独立序列(series),其 data 为 [ { name: 'April', y: 0 }, { name: 'May', y: 1 }, ... ] 形式。
以下为推荐实现方案,兼顾可读性与健壮性:
✅ 步骤一:数据预处理 —— 动态转置宽表
假设从 API 获取的数据如下(已按月份无序排列,需自动识别并排序):
本书全面介绍PHP脚本语言和MySOL数据库这两种目前最流行的开源软件,主要包括PHP和MySQL基本概念、PHP扩展与应用库、日期和时间功能、PHP数据对象扩展、PHP的mysqli扩展、MySQL 5的存储例程、解发器和视图等。本书帮助读者学习PHP编程语言和MySQL数据库服务器的最佳实践,了解如何创建数据库驱动的动态Web应用程序。
const rawData = [
{ MonthsName: 'April', AUTOLIV: 0, Continental: 0, 'Herman miller': 0, REL: 0 },
{ MonthsName: 'July', AUTOLIV: 0, Continental: 4, 'Herman miller': 0, REL: 0 },
{ MonthsName: 'June', AUTOLIV: 1, Continental: 0, 'Herman miller': 0, REL: 0 },
{ MonthsName: 'May', AUTOLIV: 1, Continental: 0, 'Herman miller': 1, REL: 1 }
];我们通过一次遍历完成转置,并自动提取所有非 X 轴字段作为系列名:
function transformToSeries(data, xKey = 'MonthsName') {
const seriesMap = new Map(); // 避免重复初始化,更安全
const monthOrder = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
// 第一遍:收集所有系列名并初始化空数组
data.forEach(item => {
Object.keys(item).forEach(key => {
if (key !== xKey && !seriesMap.has(key)) {
seriesMap.set(key, { name: key, data: [] });
}
});
});
// 第二遍:按月顺序填充数据(增强可读性与一致性)
// 若需严格按原始顺序,可跳过排序;此处按自然月序提升图表专业性
const sortedData = [...data].sort((a, b) =>
monthOrder.indexOf(a[xKey]) - monthOrder.indexOf(b[xKey])
);
sortedData.forEach(item => {
seriesMap.forEach((series, key) => {
series.data.push({
name: item[xKey], // 用作 data point 的 category label
y: Number(item[key]) || 0 // 容错:null/undefined → 0
});
});
});
return Array.from(seriesMap.values());
}
const chartSeries = transformToSeries(rawData);✅ 步骤二:Highcharts 初始化配置
关键配置点说明:
- chart.type: 'column':指定柱状图类型;
- xAxis.type: 'category':启用分类轴,支持字符串标签;
- plotOptions.column.stacking: 'normal':启用标准堆叠(累加值);
- tooltip.shared: true:推荐开启,显示所有系列在同一悬停框中。
Highcharts.chart('container', {
chart: {
type: 'column',
backgroundColor: '#f9f9f9'
},
title: {
text: '厂商月度出货量堆叠统计'
},
xAxis: {
type: 'category',
title: { text: '月份' }
},
yAxis: {
min: 0,
title: { text: '数量' }
},
tooltip: {
shared: true,
valueSuffix: ' 件'
},
plotOptions: {
column: {
stacking: 'normal',
borderRadius: 4,
dataLabels: {
enabled: true,
formatter() {
return this.y > 0 ? this.y : ''; // 仅显示非零值,避免视觉干扰
}
}
}
},
series: chartSeries
});⚠️ 注意事项与最佳实践
- 月份排序:原始数据中 MonthsName 可能乱序(如先 July 后 April)。建议按自然月序重排(如上例),或后端返回带 monthIndex 字段,避免前端硬编码。
- 字段名兼容性:若厂商名含空格或特殊字符(如 'Herman miller'),Highcharts 支持原样渲染,但确保 JavaScript 对象访问时使用方括号语法(已由 transformToSeries 自动处理)。
- 空值处理:Number(item[key]) || 0 防止 NaN 导致图表崩溃;生产环境建议补充日志告警。
- 响应式适配:添加 responsive 规则可优化移动端显示,例如缩小字体或切换为滚动轴。
- 性能提示:当数据量 > 1000 点时,启用 boost: true 或考虑聚合策略。
通过以上结构化处理,你可稳定地将任意宽表结构的动态数据转化为专业级堆叠柱状图,且具备良好的可维护性与扩展性。完整可运行示例见 JSFiddle 演示(基于 Highcharts v11+)。










