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

Laravel 6月度销售分数查询异常:列超月末日期且数据错误

Laravel 6 + Datatables 月度销售分数查询问题修正

问题描述

我正在使用Laravel 6框架结合Datatables开发功能,编写了如下代码用于查询指定月份的每日销售分数:

$tglA = Carbon::create($request->tglA)->startOfMonth()->format('Y-m-d');
$tglB = Carbon::create($request->tglB)->lastOfMonth()->format('Y-m-d');
$tglHari = Carbon::create($request->tglA)->lastOfMonth()->format('d');
$period = CarbonPeriod::create($tglA, $tglB)->toArray();

$scoreboard = HistoryPenjualan::select('kodeSales', 'departemenId');
for ($count = 1; $count <= $tglHari; $count++){
    $dateFormat = $period[$count-1]->format('Y-m-d');
    $scoreboard->selectRaw("SUM(CASE WHEN tgl = '$dateFormat' THEN score ELSE 0 END) AS '$count'");
};
$scoreboard->whereBetween('tgl', [$tglA, $tglB])
    ->where('departemenId', $request->departemenId)
    ->groupBy('departemenId')
    ->get(); 

实际运行出现两个问题:

  1. 返回结果生成了到61的列,远超当月应有的天数
  2. 部分有数据的日期(如1月30日)分数显示为0

修正方案

1. 统一查询月份,避免跨月

原代码中$tglA和$tglB可能来自不同月份的请求参数,导致$period包含多个月份的日期,同时$tglHari用字符串类型的天数,存在比较逻辑隐患。改为统一使用$request->tglA的月份作为查询范围,用整数类型的当月天数:

$targetDate = Carbon::create($request->tglA);
$tglA = $targetDate->startOfMonth()->format('Y-m-d');
$tglB = $targetDate->lastOfMonth()->format('Y-m-d');
$tglHari = $targetDate->daysInMonth; // 直接获取整数类型的当月总天数

2. 修复日期生成逻辑,避免数组越界或错误匹配

原代码依赖$period数组取日期,若跨月会导致数组长度超过当月天数,循环中取到错误日期。改为直接基于目标月份生成每日日期,同时用参数绑定避免SQL注入:

for ($count = 1; $count <= $tglHari; $count++) {
    // 直接生成当月第count天的日期,无需依赖period数组
    $dateFormat = $targetDate->copy()->startOfMonth()->addDays($count - 1)->format('Y-m-d');
    // 使用参数绑定替代字符串拼接,避免SQL注入,同时列名改为更规范的day_前缀
    $scoreboard->selectRaw("SUM(CASE WHEN tgl = ? THEN score ELSE 0 END) AS day_$count", [$dateFormat]);
}

3. 修正分组逻辑,符合SQL规范

原代码select包含kodeSales但仅按departemenId分组,严格SQL模式下会报错,且无法正确按销售代表汇总数据。需将kodeSales加入分组:

$scoreboard->whereBetween('tgl', [$tglA, $tglB])
    ->where('departemenId', $request->departemenId)
    ->groupBy('departemenId', 'kodeSales') // 加入kodeSales确保分组逻辑正确
    ->get();

如果只需要部门级别的汇总,直接去掉select中的kodeSales即可。

完整修正代码

$targetDate = Carbon::create($request->tglA);
$tglA = $targetDate->startOfMonth()->format('Y-m-d');
$tglB = $targetDate->lastOfMonth()->format('Y-m-d');
$tglHari = $targetDate->daysInMonth;

$scoreboard = HistoryPenjualan::select('kodeSales', 'departemenId');

for ($count = 1; $count <= $tglHari; $count++) {
    $dateFormat = $targetDate->copy()->startOfMonth()->addDays($count - 1)->format('Y-m-d');
    $scoreboard->selectRaw("SUM(CASE WHEN tgl = ? THEN score ELSE 0 END) AS day_$count", [$dateFormat]);
}

$scoreboard->whereBetween('tgl', [$tglA, $tglB])
    ->where('departemenId', $request->departemenId)
    ->groupBy('departemenId', 'kodeSales')
    ->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:50:29