Laravel代码无法筛选19:00至次日07:00的数据,求正确实现方案
正确代码方案及问题分析
原代码问题
你当前的代码直接将start_date拼接19:00:00、end_date拼接07:00:00作为查询范围,这种逻辑仅适用于单个跨天周期(比如从10-12 19:00到10-13 07:00),但无法覆盖多个日期内的每日晚班时间段(比如10-12到10-14期间,每天19:00到次日7:00的数据),同时当end_date晚于start_date超过一天时,会漏掉中间日期的晚班数据。
解决方案一:直接筛选时间部分(简洁高效)
利用SQL的TIME()函数提取created_at的时间部分,直接判断是否属于晚班时段(19:00之后或07:00之前),同时限定日期范围:
$startDate = $request->input('start_date'); $endDate = $request->input('end_date'); $employee_qty_in_shift2 = PatrolGateSurveillanceTransaction::where('type', 1) ->where('client_location_id', $request->client_location_id) // 限定日期范围:仅查询start_date到end_date之间的记录 ->whereDate('created_at', '>=', $startDate) ->whereDate('created_at', '<=', $endDate) // 筛选时间部分符合晚班要求的记录 ->whereRaw("TIME(created_at) >= '19:00:00' OR TIME(created_at) <= '07:00:00'") ->sum('employee_qty'); dd($employee_qty_in_shift2);
优势
- 代码简洁,性能高效(若
created_at有索引,结合日期筛选能快速定位数据) - 自动覆盖所有日期内的晚班时段,无需处理复杂跨天逻辑
解决方案二:精确匹配跨天周期(适合特定场景)
如果你的需求是从start_date 19:00到end_date 07:00的完整跨天区间(比如统计10-12晚19点到10-14早7点的所有数据),可以用Carbon处理日期时间,拆分时间段查询:
use Carbon\Carbon; $startDate = $request->input('start_date'); $endDate = $request->input('end_date'); $startDateTime = Carbon::parse($startDate)->setTime(19, 0, 0); $endDateTime = Carbon::parse($endDate)->setTime(7, 0, 0); $employee_qty_in_shift2 = PatrolGateSurveillanceTransaction::where('type', 1) ->where('client_location_id', $request->client_location_id) ->where(function ($query) use ($startDateTime, $endDateTime, $startDate, $endDate) { if ($startDate === $endDate) { // 同一天的跨天时段:当日19:00到次日07:00 $query->whereBetween('created_at', [$startDateTime, Carbon::parse($startDate)->endOfDay()]) ->orWhereBetween('created_at', [Carbon::parse($startDate)->addDay()->startOfDay(), $endDateTime]); } else { // 跨多天的情况,分三部分查询 // 1. 起始日19:00到当日结束 $query->whereBetween('created_at', [$startDateTime, Carbon::parse($startDate)->endOfDay()]) // 2. 中间所有日期的完整晚班时段 ->orWhere(function ($subQuery) use ($startDate, $endDate) { $subQuery->whereDate('created_at', '>', $startDate) ->whereDate('created_at', '<', $endDate) ->whereRaw("TIME(created_at) >= '19:00:00' OR TIME(created_at) <= '07:00:00'"); }) // 3. 结束日00:00到07:00 ->orWhereBetween('created_at', [Carbon::parse($endDate)->startOfDay(), $endDateTime]); } }) ->sum('employee_qty'); dd($employee_qty_in_shift2);
优势
- 精确控制查询的时间区间,适合有特定周期要求的场景
- 用Carbon处理日期时间,避免字符串拼接的格式错误
内容的提问来源于stack exchange,提问作者stackover flow
相关产品推荐
相关产品推荐

