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

如何用单条查询获取指定周的员工排班数据(Laravel场景)

可以合并为单条查询实现,核心思路是提前生成目标周7天对应的日期与星期几映射,将7组查询条件通过OR逻辑拼接在同一个查询语句中,避免循环查询。

实现代码

首先预处理目标周的日期信息:

$startDate = new Carbon($data['start_date']);
$startDate->startOfWeek(Carbon::SUNDAY);

// 生成一周7天的日期、对应星期几数组
$weekDays = [];
for ($i = 0; $i <= 6; $i++) {
    $weekDays[] = [
        'date' => $startDate->copy()->format('Y-m-d'),
        'week_day' => $startDate->dayOfWeek
    ];
    $startDate->addDay();
}

执行单条查询获取所有符合条件的排班记录:

$schedules = StaffSchedule::where(function ($query) use ($weekDays) {
    // 把每天的查询条件用OR逻辑拼接
    foreach ($weekDays as $day) {
        $query->orWhere(function ($subQuery) use ($day) {
            $subQuery->where('start_date', '<=', $day['date'])
                ->where('day_of_week', $day['week_day'])
                ->where(function ($endCondition) use ($day) {
                    $endCondition->where('end_date', '>=', $day['date'])
                        ->orWhereNull('end_date');
                });
        });
    }
})
->orderBy('user_id')
->get();

如果你需要和原有逻辑一样按天分组存储结果,可以对查询返回的集合做二次匹配分组即可。

生成的SQL结构参考

SELECT * FROM `schedules` 
WHERE (
    (start_date <= '2021-06-13' AND day_of_week = 0 AND (end_date >= '2021-06-13' OR end_date IS NULL))
    OR (start_date <= '2021-06-14' AND day_of_week = 1 AND (end_date >= '2021-06-14' OR end_date IS NULL))
    OR -- 剩余5天的条件依次拼接
)
ORDER BY `user_id` ASC

优化建议

  1. 建议将表中start_date、end_date字段的类型从VARCHAR改为DATE,既可以提升查询性能,也能避免字符串格式异常导致的日期比较错误。
  2. 可以新增(day_of_week, start_date, end_date)联合索引,大幅提升该查询的执行速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 11:45:06