如何在 PHP 中动态生成按月和木材类型分组的 MySQL 汇总报表

本文详解如何通过修正 sql 条件逻辑,正确按月份和木材型号(如 a-001、a-003)分别汇总立方米(cubic)数据,并在 html 表格中动态渲染结果。

在实际木材加工或仓储管理系统中,常需按月统计不同木材类型的出库/加工量(单位:m³)。你当前遇到的核心问题是:SQL 中误将 cubic 字段用于 IF() 的判断条件,而实际应根据 wood 字段匹配型号,再对 cubic 值求和。原始查询中 SUM(IF(cubic='A-001',1,0)) 本质是在计数(且逻辑错误),而非累加体积值——这导致所有分类列显示为 0.0 m³,仅 SUM(cubic) 正确。

✅ 正确做法是:使用 SUM(IF(wood = 'A-001', cubic, 0)) —— 即当 wood 字段匹配特定型号时,取其对应的 cubic 数值参与求和;否则计入 0。同时注意:

  • MySQL 中小数分隔符为英文句点(.),但你的示例数据使用了逗号(,),请确保数据库中 cubic 列为 DECIMAL 或 FLOAT 类型,且数据已规范存储(如 0.25 而非 0,25),否则会导致隐式转换失败或求和异常;
  • MONTH(date) 仅返回月份数字(1–12),若需显示“2月”等中文名称,可在 PHP 中映射处理;
  • WHERE machine='mebor2' 与示例数据中的 mebor1 不一致,请根据实际需求调整过滤条件。

以下是修正后的完整 PHP + MySQL 实现代码(含健壮性增强):

    = DATE_SUB(NOW(), INTERVAL 12 MONTH) -- 可选:限制近一年数据
            GROUP BY month
            ORDER BY month ASC";

        $result_list = mysqli_query($conn, $sql_list);

        if (!$result_list) {
            echo "";
        } elseif (mysqli_num_rows($result_list) === 0) {
            echo "";
        } else {
            while ($row = mysqli_fetch_assoc($result_list)) {
                // 将数字月份转为中文(可选)
                $monthName = ['1月','2月','3月','4月','5月','6月',
                              '7月','8月','9月','10月','11月','12月'][$row['month'] - 1] ?? $row['month'] . '月';
                ?>
                
月份 Nyár Tölgy VTölgy Cser 合计
查询失败:" . mysqli_error($conn) . "
暂无数据

? 关键改进说明

  • 使用 COALESCE(..., 0) 防止 NULL 值在前端显示为空白;
  • number_format($val, 2, '.', '') 统一使用英文小数点,避免 locale 导致格式混乱;
  • 添加 htmlspecialchars() 防止 XSS(尤其当字段内容可能含用户输入时);
  • 增加错误处理与空数据提示,提升生产环境鲁棒性;
  • ORDER BY month ASC 确保月份升序排列,便于阅读。

? 进阶建议
若木材类型较多或动态变化,可考虑用 CASE WHEN 或预聚合视图替代硬编码 IF;更灵活的方案是先查出所有唯一 wood 值,再动态构建列名与 SQL,结合 PDO 的预处理语句实现完全动态报表。