如何在Laravel查询构建器中分别统计不同状态的时间槽数量?
解决方案
你可以使用条件聚合函数,通过SUM(CASE WHEN ...)来分别统计不同状态的时间槽数量,同时注意不要在WHERE里过滤掉某一种状态的记录,否则会导致另一种状态的计数不准确或缺失。
修改后的查询代码如下:
$appointments = DB::table('appointments') ->join('times', 'times.appointment_id', '=', 'appointments.id') ->where('appointments.status', 0) ->selectRaw(" appointments.id, appointments.date, SUM(CASE WHEN times.status = 1 THEN 1 ELSE 0 END) AS booked_slots, SUM(CASE WHEN times.status = 0 THEN 1 ELSE 0 END) AS available_slots ") ->groupBy('appointments.id', 'appointments.date') ->orderBy('appointments.id', 'asc') ->get();
代码说明:
SUM(CASE WHEN times.status = 1 THEN 1 ELSE 0 END):遍历所有关联的times记录,每当时间槽状态为1时累加1,最终得到已预订的数量。SUM(CASE WHEN times.status = 0 THEN 1 ELSE 0 END):同理,统计状态为0的可用时间槽数量。- 移除了原查询中
where('times.status',0)的过滤条件,确保能保留所有关联的时间槽记录,让两种状态的计数都准确。
如果你的Laravel版本支持,也可以用DB::raw()结合COUNT(IF(...))简化写法,效果一致:
$appointments = DB::table('appointments') ->join('times', 'times.appointment_id', '=', 'appointments.id') ->where('appointments.status', 0) ->select([ 'appointments.id', 'appointments.date', DB::raw("COUNT(IF(times.status = 1, 1, NULL)) AS booked_slots"), DB::raw("COUNT(IF(times.status = 0, 1, NULL)) AS available_slots") ]) ->groupBy('appointments.id', 'appointments.date') ->orderBy('appointments.id', 'asc') ->get();
补充:如果存在没有关联任何时间槽的预约,
join会过滤掉这类数据。若需要保留这类预约并显示计数为0,可以改用leftJoin替代join。
内容的提问来源于stack exchange,提问作者Code Kris
相关产品推荐
相关产品推荐

