您需要遍历所有 worker 然后为每个工人在其“范围”内找到工作,试试这个
$conn = $conn = new PDO("mysql:host=localhost;dbname=test", 'root', '');
$result = $conn->query("SELECT * FROM worker");
$allWorkers = [];
foreach($result as $row)
{
$allWorkers[] = array(
'id'=> $row["id"],
'latitude'=>$row["latitude"],
'longitude'=>$row["longitude"],
'work_radius'=> $row["work_radius"]
);
}
$distance_query = 'SELECT
*, (
6371 * acos (
cos ( radians(:latitude) )
* cos( radians( latitude) )
* cos( radians( longitude ) - radians(:longitude) )
+ sin ( radians(:latitude) )
* sin( radians( latitude) )
)
) AS distance
FROM jobs
having distance < :work_radius
ORDER BY distance
LIMIT 0 , 20;';
$workers_jobs = array();
$stmt = $conn->prepare($distance_query);
foreach( $allWorkers as $worker)
{
$stmt->bindParam(':latitude', $worker['latitude']);
$stmt->bindParam(':longitude', $worker['longitude']);
$stmt->bindParam(':work_radius', $worker['work_radius']);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$workers_jobs[$worker['id']]['id'] = $row['id'];
$workers_jobs[$worker['id']]['latitude'] = $row['latitude'];
$workers_jobs[$worker['id']]['longitude'] = $row['longitude'];
}
}
//$workers_jobs 为每个工人和他的工作保留一行
更新
假设您在工作表中有一个额外的列“Shift”(varchar 50)
+----+-----------+-----------+---------+
| id | latitude | longitude | Shift |
+----+-----------+-----------+---------+
| 1 | 51.919438 | 19.145136 | morning |
| 2 | 49.852276 | 15.015519 | evening |
| 3 | 49.208705 | 11.946989 | night |
+----+-----------+-----------+---------+
如何将其包含在您的 $distance_query 中?很好地绑定 IN 有点棘手,所以在继续之前你必须阅读 this part
$conn = $conn = new PDO("mysql:host=localhost;dbname=test", 'root', '');
$result = $conn->query("SELECT * FROM worker");
$allWorkers = [];
foreach($result as $row)
{
$allWorkers[] = array(
'id'=> $row["id"],
'latitude'=>$row["latitude"],
'longitude'=>$row["longitude"],
'work_radius'=> $row["work_radius"]
);
}
//** bind IN - placeholders**//
$shifts = ['morning','night'];
$in = '';
foreach ($shifts as $i => $item)
{
$key = ':shift'.$i;
$in .= "$key,";
}
$in = rtrim($in, ',');
//** bind IN - placeholders end **//
$distance_query = 'SELECT
*, (
6371 * acos (
cos ( radians(:latitude) )
* cos( radians( latitude) )
* cos( radians( longitude ) - radians(:longitude) )
+ sin ( radians(:latitude) )
* sin( radians( latitude) )
)
) AS distance
FROM jobs
where shift IN (' . $in . ')
having distance < :work_radius
ORDER BY distance
LIMIT 0 , 20;';
$workers_jobs = array();
$stmt = $conn->prepare($distance_query);
foreach( $allWorkers as $worker)
{
$stmt->bindParam(':latitude', $worker['latitude']);
$stmt->bindParam(':longitude', $worker['longitude']);
$stmt->bindParam(':work_radius', $worker['work_radius']);
//** bind IN - values**//
$shifts = ['morning','night'];
$in = '';
foreach ($shifts as $i => $item)
{
$key = ':shift'.$i;
$stmt->bindParam($key, $item);
}
//** bind IN - values ends**//
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$workers_jobs[$worker['id']]['id'] = $row['id'];
$workers_jobs[$worker['id']]['latitude'] = $row['latitude'];
$workers_jobs[$worker['id']]['longitude'] = $row['longitude'];
}
}
echo '<pre>'; print_r($workers_jobs);