I have a table that has multiple records with the same foreign key (work_order_id). Those records have a status field (Pending or Completed). I only want to return those work_order_id's where all the records for that work_order_id match status = Completed. If there are 5 records with work_order_id 95000 and 1 of them has a status of Pending and the rest are status = Completed I do not want to return work_order_id 95000 in the result.
I am currently using a foreach loop in PHP that is not efficient at all. As the record count grows I am running into the query timeout.
$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;
}
}
I ended up coming up with a solution. I used two queries. First one gets the list of work_order_id's. I pass that into a where in on the second query to get my result.
$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();
I don't know if this will work as I don't have you database, but why not join the tables together and group the related records based on the count.
Something like.
$work_orders = DB::table('work_orders')
->select(
DB::raw('COUNT(work_order_tasks.work_order_id) count'),
'work_orders.*',
'vehicles.vin',
'work_orders.transportation_type as transport',
'clients.name as client_name',
'events.event_name as event_name'
)
->havingRaw('count>0')
->groupBy('work_orders.id')
->where('status', '!=', 'Closed')
->where("work_order_tasks.status", "<>", "Completed")
->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')
->leftJoin('work_order_tasks', 'work_orders.id', '=','work_order_tasks.work_order_id')
->get();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.