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

Laravel 7使用whereBetween查询两个月区间数据的问题

问题:Laravel中跨月份区间查询数据异常

我需要查询两个月区间内的数据(例如8月到9月),但当前代码的区间查询逻辑无法得到预期结果,问题出在这段代码:

else if ($bulan1 != "semua" && $bulan2 != "semua") {
   $query->whereBetween(DB::raw('MONTH(kred_kep_aktf_kompetensi.mulai)'), [$bulan1, $bulan2]);
}

以下是完整的函数代码:

public function load_kompetensi(Request $request) {
        $jenis_kegiatan = $request->input('jenis_kegiatan');
        $bulan1 = $request->input('bulan1', 'semua');
        $bulan2 = $request->input('bulan2', 'semua');
        $tahun = $request->input('tahun', 'semua');
        $unit = $request->input('unit', 'semua');

        try {
            $query = DB::connection('database')
                ->table('kred_kep_aktf_kompetensi')
                ->join('Karyawan', 'kred_kep_aktf_kompetensi.nid_karyawan', '=', 'Karyawan.NID')
                ->join('kred_jenis_kegiatan', 'kred_kep_aktf_kompetensi.id_jenis_kegiatan', '=', 'kred_jenis_kegiatan.id')
                ->join('kred_jenis_peran', 'kred_kep_aktf_kompetensi.id_peran', '=', 'kred_jenis_peran.id')
                ->select('kred_kep_aktf_kompetensi.*', 'Karyawan.Nama', 'kred_jenis_kegiatan.nama_kegiatan', 'kred_jenis_peran.nama_peran');

            if (session('jabatane') == "Pelaksana") {
                $query->where('kred_kep_aktf_kompetensi.nid_karyawan', session('nidkaryawan'));
            } else if (session('jabatane') == "Subag/Kanit") {
                $query->where('kred_kep_aktf_kompetensi.id_unit_kerja', session('unite_id'));
            }

            if ($unit != "semua") {
                $query->where('kred_kep_aktf_kompetensi.id_unit_kerja', $unit);
            }

            if ($jenis_kegiatan && $jenis_kegiatan != 'semua') {
                $query->where('kred_kep_aktf_kompetensi.id_jenis_kegiatan', $jenis_kegiatan);
            }


            if ($bulan1 != "semua" && $tahun != "semua") {
                $query->whereMonth('kred_kep_aktf_kompetensi.mulai', $bulan1)
                      ->whereYear('kred_kep_aktf_kompetensi.mulai', $tahun);
            } else if ($bulan1 != "semua" && $bulan2 == "semua") {
                $query->whereMonth('kred_kep_aktf_kompetensi.mulai', $bulan1);
            } else if ($bulan1 != "semua" && $bulan2 != "semua") {
                $query->whereBetween(DB::raw('MONTH(kred_kep_aktf_kompetensi.mulai)'), [$bulan1, $bulan2]);
            } else if ($tahun != "semua") {
                $query->whereYear('kred_kep_aktf_kompetensi.mulai', $tahun);
            }

            $files = $query->orderBy('kred_kep_aktf_kompetensi.id', 'asc')->get();

            foreach ($files as $file) {
                $file->mulai = Carbon::parse($file->mulai)->format('d-m-Y');
                $file->akhir = Carbon::parse($file->akhir)->format('d-m-Y');
            }

        } catch (\Throwable $th) {
            throw $th;
        }

        return view("keperawatan.list_aktf_kompetensi_load", ['files' => $files]);
    }

kred_kep_aktf_kompetensi.mulai字段格式为YYYY-MM-DD HH:MM:SS,示例值:2024-08-09 06:51:30.000。我已测试原生SQL语句:

SELECT * FROM kred_kep_aktf_kompetensi
WHERE (MONTH(mulai) BETWEEN 8 AND 9);

该语句能返回预期结果,但将硬编码的8、9替换为请求传入的数字类型参数$bulan1和$bulan2后,仍然无法得到正确结果,寻求解决方法。


解决办法

1. 修正参数类型与区间顺序

首先确保$bulan1和$bulan2是整数类型,且区间顺序正确(避免出现$bulan1=9、$bulan2=8的反向区间):

else if ($bulan1 != "semua" && $bulan2 != "semua") {
    // 转换为整数类型
    $bulan1 = (int)$bulan1;
    $bulan2 = (int)$bulan2;
    // 交换顺序确保左值小于等于右值
    if ($bulan1 > $bulan2) {
        [$bulan1, $bulan2] = [$bulan2, $bulan1];
    }
    $query->whereBetween(DB::raw('MONTH(kred_kep_aktf_kompetensi.mulai)'), [$bulan1, $bulan2]);
}

2. 补充年份过滤(可选但推荐)

当前逻辑中,月份区间查询未关联年份,会返回所有年份的对应月份数据。如果需要限定在指定年份,需补充年份条件:

else if ($bulan1 != "semua" && $bulan2 != "semua") {
    $bulan1 = (int)$bulan1;
    $bulan2 = (int)$bulan2;
    if ($bulan1 > $bulan2) {
        [$bulan1, $bulan2] = [$bulan2, $bulan1];
    }
    $query->whereBetween(DB::raw('MONTH(kred_kep_aktf_kompetensi.mulai)'), [$bulan1, $bulan2]);
    // 如果传入了年份,添加年份过滤
    if ($tahun != "semua") {
        $query->whereYear('kred_kep_aktf_kompetensi.mulai', $tahun);
    }
}

3. 优化为日期范围查询(更高效)

直接基于日期字段做范围查询,既能利用数据库索引提升性能,也能自然解决跨年份问题:

else if ($bulan1 != "semua" && $bulan2 != "semua") {
    // 确定目标年份,优先使用传入的tahun,否则用当前年份
    $targetYear = $tahun != "semua" ? $tahun : Carbon::now()->year;
    // 构造区间起始和结束日期
    $startDate = Carbon::create($targetYear, $bulan1, 1)->startOfMonth();
    $endDate = Carbon::create($targetYear, $bulan2, 1)->endOfMonth();
    // 直接查询日期范围
    $query->whereBetween('kred_kep_aktf_kompetensi.mulai', [$startDate, $endDate]);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 10:05:55