Laravel Eloquent关联JOIN查询问题:如何获取所有时段及有效参会人数统计
解决Laravel Eloquent中获取所有时段并统计有效预订的问题
嘿,我完全懂你遇到的麻烦!你的查询现在只返回有有效预订的时段,核心问题出在你把invoices.type的过滤条件放在了主查询的where里——当用leftJoin关联表时,那些没有匹配到有效参会者的时段,对应的invoices字段会变成null,而SQL中null != 'IncompleteOrder'会被判定为false,直接把这些无有效预订的时段过滤掉了。
要获取所有可用时段,同时正确统计有效预订数,你需要把发票的过滤逻辑整合到关联查询中,而不是主查询的全局条件里。这里有个最靠谱的实现方式:
use Illuminate\Support\Facades\DB; $this->selectRaw('timeslots.id, timeslots.time_from , timeslots.time_till, duration_minutes, count(attendees.id) as bookedSlots, capacity as total, capacity - count(attendees.id) as leftTickets') ->where('timeslots.project_id', $projectId) ->whereDate('time_from', '=', $date) ->leftJoin('attendees', function($query) { $query->on('timeslots.id', '=', 'attendees.timeslot_id') // 过滤生效且未取消的参会者 ->where('attendees.is_live', '=', 1) ->where('attendees.is_cancelled', '=', 0) // 额外确保对应的发票不是"IncompleteOrder" ->whereExists(function($subquery) { $subquery->select(DB::raw(1)) ->from('invoices') ->whereColumn('invoices.id', 'attendees.invoice_id') ->where('invoices.type', '!=', 'IncompleteOrder'); }); }) ->groupBy('timeslots.id') ->get();
这个方案的优势:
- 保留所有时段:因为用的是
leftJoin,不管时段有没有有效预订,都会被返回;没有有效预订的时段,bookedSlots会显示为0,leftTickets等于时段容量。 - 精准统计有效预订:在关联
attendees时就通过whereExists过滤掉了发票状态不符合的参会者,最终统计的都是完全符合条件的有效预订。
另外提个小细节:如果你的数据库开启了严格模式,确保groupBy包含所有被选中的非聚合字段(或者依赖主键timeslots.id的特性,大多数情况下主键分组是合法的)。
内容的提问来源于stack exchange,提问作者Dave Driesmans
相关产品推荐
相关产品推荐

