
本文详解如何将数据库中多个字段(如 technician_1 和 technician_2)的值统一归类计数,并动态生成 chart.js 柱状图,避免重复查询、提升性能与可维护性。
本文详解如何将数据库中多个字段(如 technician_1 和 technician_2)的值统一归类计数,并动态生成 chart.js 柱状图,避免重复查询、提升性能与可维护性。
在使用 Chart.js 展示人员工作量(如工单分配)时,常需将同一技术人员出现在不同字段(如 technician_1 和 technician_2)中的记录合并统计。原始方案中为每位技术人员编写独立 SQL 查询(如 WHERE technician_1='Ema' OR technician_2='Ema'),不仅代码冗余、难以扩展,还存在大小写敏感、SQL 注入风险及性能瓶颈等问题。
✅ 推荐做法:使用单次聚合查询 + PHP 数组归一化处理
以下为安全、高效、可扩展的完整实现:
1. 数据库层:一次查询汇总所有技术人员出现次数
<?php // 使用 UNION ALL 合并两列值,再 GROUP BY 统计频次(忽略大小写,统一转小写便于去重)
$sql = "
SELECT LOWER(technician) as tech, COUNT(*) as cnt FROM (
SELECT technician_1 AS technician FROM tb_ticket
UNION ALL
SELECT technician_2 AS technician FROM tb_ticket
) AS t
WHERE technician IS NOT NULL AND TRIM(technician) != ''
GROUP BY LOWER(technician)
ORDER BY cnt DESC
";
$result = mysqli_query($koneksi, $sql);
$techCounts = [];
while ($row = mysqli_fetch_assoc($result)) {
$techCounts[$row['tech']] = (int)$row['cnt'];
}
// 此时 $techCounts = ['ema' => 3, 'tom' => 4, 'ana' => 1, 'lisa' => 2]
?>
2. 前端 Chart.js 配置:动态注入标签与数据
<canvas id="myChart"></canvas><script src="https://cdn.jsdelivr.net/npm/chart.js"></script><script>
const ctx = document.getElementById('myChart').getContext('2d');
const labels = <?php echo json_encode(array_keys($techCounts)); ?>;
const data = <?php echo json_encode(array_values($techCounts)); ?>;
new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: '工单分配总数(technician_1 + technician_2)',
data: data,
backgroundColor: [
'#1B4F72', '#21618C', '#2874A6', '#2E86C1', '#3498DB', '#5DADE2', '#85C1E9'
].slice(0, labels.length),
borderWidth: 1
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
ticks: {
precision: 0,
stepSize: 1
}
},
x: {
ticks: {
autoSkip: false
}
}
},
plugins: {
legend: {
position: 'top',
}
}
}
});
</script>
⚠️ 关键注意事项:
- 大小写处理:数据库中姓名可能大小写混用(如 'EMA', 'Ema', 'ema'),务必在 SQL 中用 LOWER() 或 UPPER() 统一归一化,否则会被视为不同人员;
- 空值与空白值过滤:WHERE technician IS NOT NULL AND TRIM(technician) != '' 防止空字符串或 NULL 干扰统计;
- 避免 SQL 注入:本方案未拼接用户输入,全程使用静态 SQL,安全性高;若需支持动态筛选(如按日期范围),务必使用预处理语句(mysqli_prepare);
- 性能优化:相比 4 次独立查询,单次聚合查询显著减少数据库往返开销,尤其在数据量大时优势明显;
- 可扩展性:如后续新增 technician_3 字段,只需在 UNION ALL 子句中追加一行即可,无需修改 PHP 逻辑与前端结构。
通过该方法,你不仅能准确得到 Ema=3, Tom=4, Ana=1, Lisa=2 的统计结果,还能构建出健壮、可维护、面向未来的可视化报表系统。











