【发布时间】:2020-12-10 18:35:02
【问题描述】:
我有一个表,其中包含多个具有相同外键 (work_order_id) 的记录。这些记录有一个状态字段(Pending 或 Completed)。我只想返回那些 work_order_id 的所有记录都匹配状态 = 已完成的 work_order_id。如果有 5 条 work_order_id 为 95000 的记录,其中 1 条状态为 Pending,其余为 status = Completed,我不想在结果中返回 work_order_id 95000。
我目前在 PHP 中使用了一个根本没有效率的 foreach 循环。随着记录数的增加,我遇到了查询超时。
$work_orders = DB::table('work_orders')
->select(
'work_orders.*',
'vehicles.vin',
'work_orders.transportation_type as transport',
'clients.name as client_name',
'events.event_name as event_name'
)
->where('status', '!=', 'Closed')
->leftJoin('vehicles', 'vehicles.id', '=', 'work_orders.gsm_vehicle_id')
->leftJoin('clients', 'clients.id', '=', 'work_orders.client_id')
->leftJoin('events', 'events.id', '=', 'work_orders.gsm_event_id')
->get();
foreach ($work_orders as $wo) {
$tasks = DB::table("work_order_tasks")
->where("work_order_id", $wo->id)
->where("status", "<>", "Completed")
->count();
if ($tasks == 0) {
$results[] = $wo;
}
}
我最终想出了一个解决方案。我使用了两个查询。第一个获取 work_order_id 的列表。我将它传递给第二个查询的 where in 以获得我的结果。
$completedWO = DB::select(
DB::raw("
SELECT DISTINCT
r.work_order_id
FROM
work_order_tasks AS r
WHERE
NOT EXISTS (
SELECT
work_order_id
FROM
work_order_tasks
WHERE
work_order_id = r.work_order_id
AND STATUS = 'Pending')
ORDER BY r.work_order_id ASC
"));
$output = array_map(function ($object) { return $object->work_order_id; }, $completedWO);
$wo = "'" . implode("', '", $output) . "'";
$results = DB::table('work_orders')
->select(
'work_orders.*',
'vehicles.vin',
'work_orders.transportation_type as transport',
'clients.name as client_name',
'events.event_name as event_name'
)
->leftJoin('vehicles', 'vehicles.id', '=', 'work_orders.gsm_vehicle_id')
->leftJoin('clients', 'clients.id', '=', 'work_orders.client_id')
->leftJoin('events', 'events.id', '=', 'work_orders.gsm_event_id')
->where('work_orders.status', '!=', 'Closed')
->whereRaw('work_orders.id IN ('. $wo . ')')
->orderBy('work_orders.id', 'ASC')
->get();
【问题讨论】: