PHP实现可用工人等量分配未完成工作的问题求助
PHP实现工人等量分配未完成工作
现有场景:已通过代码获取到包含2位工人的数组,需要将未完成工作等量分配给每位工人,但当前分配代码会把所有工作都分配给第一位工人,期望实现如2位工人分配4项工作时每人各得2项的效果。
获取可用工人数组代码
if (!isset($array_worker)){ $array_worker = array(); } $stmt = $dbh->prepare("SELECT username FROM group_members WHERE grp_id = :grp_id AND statut > 0 AND specification != 2"); $stmt->bindValue(':grp_id', $grp_id); $stmt->execute(); $data = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($data as $key => $value){ if (!in_array($value['username'], $array_worker)){ array_push($array_worker, $value['username']); } }
问题代码(分配逻辑)
$n = 0; for ($i = 0; $i < count_worknotdone($grp_id); $i++) { if ($n >= count($array_worker)){ $n = 0; } $stmt = $dbh->prepare("UPDATE work SET worker = :worker WHERE grp_id = :grp_id AND worker IS NULL"); $stmt->bindValue(':worker ', $array_worker[$n]); $stmt->bindValue(':grp_id', $grp_id); $stmt->execute(); $n++; }
问题原因
这段代码的核心问题是每次执行UPDATE语句时,会修改所有满足worker IS NULL的记录,第一次循环就把所有未完成工作全部分配给了第一位工人,后续循环没有可更新的记录,导致所有工作都归第一位工人。
解决方法
方法1:修改UPDATE语句,每次只更新一条记录
在UPDATE语句末尾添加LIMIT 1,确保每次循环只分配一项工作:
$n = 0; $workerCount = count($array_worker); if ($workerCount === 0) { exit; // 无可用工人时直接退出 } $totalWork = count_worknotdone($grp_id); for ($i = 0; $i < $totalWork; $i++) { $currentWorker = $array_worker[$n % $workerCount]; // 用取模简化循环逻辑 $stmt = $dbh->prepare("UPDATE work SET worker = :worker WHERE grp_id = :grp_id AND worker IS NULL LIMIT 1"); $stmt->bindValue(':worker', $currentWorker); $stmt->bindValue(':grp_id', $grp_id); $stmt->execute(); $n++; }
方法2:先获取所有未完成工作ID,再批量分配(更高效)
先一次性取出所有未完成工作的ID,再通过循环逐个分配,减少数据库查询次数:
// 1. 获取所有未完成工作的ID $stmt = $dbh->prepare("SELECT id FROM work WHERE grp_id = :grp_id AND worker IS NULL"); $stmt->bindValue(':grp_id', $grp_id); $stmt->execute(); $workIds = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); $workerCount = count($array_worker); if ($workerCount === 0 || empty($workIds)) { exit; } // 2. 循环分配工作 foreach ($workIds as $index => $workId) { $currentWorker = $array_worker[$index % $workerCount]; $stmt = $dbh->prepare("UPDATE work SET worker = :worker WHERE id = :work_id"); $stmt->bindValue(':worker', $currentWorker); $stmt->bindValue(':work_id', $workId); $stmt->execute(); }
额外优化:简化工人数组获取逻辑
如果group_members表中username不会重复出现,可以直接用FETCH_COLUMN获取工人数组,省去去重循环:
$stmt = $dbh->prepare("SELECT username FROM group_members WHERE grp_id = :grp_id AND statut > 0 AND specification != 2"); $stmt->bindValue(':grp_id', $grp_id); $stmt->execute(); $array_worker = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
内容的提问来源于stack exchange,提问作者julian goncalves
相关产品推荐
相关产品推荐

