You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP查询年度服务数据时如何补全数组缺失年份的0值条目

问题背景
  • 需求为统计合同内住宿(HEBERGEMENT)、餐饮(RESTAURATION)两类服务的年度营收总额,结果存入数组后传递给JavaScript渲染动态图表,当前基础查询功能运行正常
  • 现存故障:部分年份无对应类别的服务数据时,原有循环逻辑不会补全缺失条目,导致两个分类的数组长度不一致、年份顺序不匹配,传递到前端后图表列错位,无法正常渲染
原有实现代码
while ($data = $requete1->fetch()) {
    // Hébergement : 
    if($data['P_TYPE']=="HEBERGEMENT"){    
        $hebergement[] =  array("label"=> $data['ANNEE'], "y"=> $data['ca_total']);
    }

    // Restauration : 
    if($data['P_TYPE']=="RESTAURATION"){    
        $restauration[] =   array("label"=> $data['ANNEE'], "y"=> $data['ca_total']);
    }
}
预期输出结构

统计年份范围内,两类服务对应的数组需包含所有年份条目,无对应数据的年份y值填充为0,参考结构如下:

// Hébergement années non comprises en bdd :  
$hebergement[] = array("label"=> "2021", "y"=> 68279);
$hebergement[] = array("label"=> "2020", "y"=> 30457);
$hebergement[] = array("label"=> "2019", "y"=> 0);
$hebergement[] = array("label"=> "2018", "y"=> 57993);
$hebergement[] = array("label"=> "2017", "y"=> 49702);
$hebergement[] = array("label"=> "2016", "y"=> 45493);
$hebergement[] = array("label"=> "2015", "y"=> 38460);
    
// Restauration années non comprises en bdd :  
$restauration[] = array("label"=> "2021", "y"=> 12117);
$restauration[] = array("label"=> "2020", "y"=> 697);
$restauration[] = array("label"=> "2019", "y"=> 2687);
$restauration[] = array("label"=> "2018", "y"=> 0);
$restauration[] = array("label"=> "2017", "y"=> 40);
$restauration[] = array("label"=> "2016", "y"=> 350);
$restauration[] = array("label"=> "2015", "y"=> 200);
原有补全逻辑的问题

之前尝试的补全代码依赖单次循环内的临时年份差值判断,没有先固定完整的统计年份范围,也没有对两类数据做独立的键值映射,会出现补错位、漏补的情况,无法达到预期效果。

正确实现方案

核心逻辑分三步:先确定完整统计年份范围、给两类数据初始化所有年份的默认值为0、遍历查询结果覆盖实际营收值,最后按统一顺序生成前端需要的数组。

// --------------------------
// 步骤1:确定统计年份范围
// --------------------------
// 方式1:手动指定起止年份,根据业务需求修改
$startYear = 2015;
$endYear = 2021;

/*
// 方式2:自动从查询结果中取最小/最大年份作为范围,不需要手动写死
$allData = $requete1->fetchAll(); // 一次性取出所有结果,不能用fetch多次遍历
$years = array_column($allData, 'ANNEE');
$startYear = min($years);
$endYear = max($years);
*/

// 初始化两类数据的临时映射,以年份为键,默认营收为0
$hebergementMap = [];
$restaurationMap = [];
for ($y = $startYear; $y <= $endYear; $y++) {
    $hebergementMap[$y] = 0;
    $restaurationMap[$y] = 0;
}

// --------------------------
// 步骤2:遍历查询结果填充实际值
// --------------------------
// 如果用方式2自动取年份,这里把$requete1->fetch()改成遍历$allData即可
while ($data = $requete1->fetch()) {
    $year = $data['ANNEE'];
    // 跳过不在统计范围内的异常数据
    if ($year < $startYear || $year > $endYear) {
        continue;
    }
    if ($data['P_TYPE'] == "HEBERGEMENT") {
        $hebergementMap[$year] = $data['ca_total'];
    }
    if ($data['P_TYPE'] == "RESTAURATION") {
        $restaurationMap[$year] = $data['ca_total'];
    }
}

// --------------------------
// 步骤3:按统一顺序生成前端需要的数组
// --------------------------
$hebergement = [];
$restauration = [];
// 此处从最大年份倒序遍历,和示例的年份排序保持一致;需要正序就改成for($y = $startYear; $y <= $endYear; $y++)
for ($y = $endYear; $y >= $startYear; $y--) {
    $hebergement[] = [
        "label" => (string)$y,
        "y" => $hebergementMap[$y]
    ];
    $restauration[] = [
        "label" => (string)$y,
        "y" => $restaurationMap[$y]
    ];
}

注意:如果选择自动从查询结果取年份范围的方案,必须用fetchAll()一次性取出所有结果集,不能重复调用fetch()遍历两次,否则第二次遍历拿不到数据。

内容的提问来源于stack exchange,提问作者user19487444

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:18:16