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

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();

这个方案的优势:

  1. 保留所有时段:因为用的是leftJoin,不管时段有没有有效预订,都会被返回;没有有效预订的时段,bookedSlots会显示为0,leftTickets等于时段容量。
  2. 精准统计有效预订:在关联attendees时就通过whereExists过滤掉了发票状态不符合的参会者,最终统计的都是完全符合条件的有效预订。

另外提个小细节:如果你的数据库开启了严格模式,确保groupBy包含所有被选中的非聚合字段(或者依赖主键timeslots.id的特性,大多数情况下主键分组是合法的)。

内容的提问来源于stack exchange,提问作者Dave Driesmans

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 13:07:31