Как сделать MYSQL-запрос на выбор из двух таблиц на основе долготы, широты и радиуса?

0

У меня 2 таблицы. таблица рабочих мест и рабочих мест. Рабочий стол принимает latitude, longitude и work radius. Таблица рабочих мест имеет latitude и longitude. Мне нужен запрос выбора, который получает строки из таблицы заданий, но в пределах work radius работы рабочей таблицы.

Ниже приведена структура таблиц и то, что у меня есть до сих пор, это выбор из таблицы на основе широты и долготы.

Спасибо за любую помощь.

Рабочий стол:

CREATE TABLE "worker" (
  "id" varchar(25) NOT NULL,
  "latitude" varchar(25) NOT NULL,
  "longitude" varchar(25) NOT NULL,
  "work_radius" int(25) NOT NULL,
  "address" varchar(255) NOT NULL,
  PRIMARY KEY ("id")
);

Таблица рабочих мест:

CREATE TABLE "jobs" (
  "id" varchar(25) NOT NULL,
  "latitude" varchar(25) NOT NULL,
  "longitude" varchar(25) NOT NULL,
  "address" varchar(255) NOT NULL,
  PRIMARY KEY ("id")
);

Выберите запрос:

$jobs_load = $dbh->prepare("
SELECT
    '*',
    (
        6371 *
        acos(
            cos( radians( :lat_id ) ) *
            cos( radians( 'lat_id' ) ) *
            cos(
                radians( 'long_id' ) - radians( :long_id )
            ) +
            sin(radians(:lat_id) *
            sin(radians('lat_id'))
        )
    ) 'work_radius'
FROM
    'jobs'
HAVING
    'work_radius' < :work_radius
ORDER BY
    'work_radius'
LIMIT
    25");
  • 0
    Вы уверены, что используете MySQL? Имена таблиц и столбцов в кавычках обычно не поддерживаются MySQL .. если MySQL не добавил ANSI в своем sql-режиме.
  • 0
    Да, я использую MYSQL и, очевидно, он поддерживается на моем сервере. :)
Показать ещё 1 комментарий
Теги:

1 ответ

1
Лучший ответ

Вам нужно зациклиться на всем 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 немного сложна, поэтому, прежде чем двигаться дальше, вы должны прочитать эту часть

$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);  
  • 0
    Спасибо за ответ, однако, это делает это для всех рабочих и рабочих мест. Мне нужно сделать это только для одного работника за раз. Таким образом, в результате $ нужно выбрать одного работника по идентификатору, а затем сопоставить задания на основе местоположения этого работника и радиуса работы.
  • 0
    Это работает и для одного, просто передайте id работника, поэтому он выберет только одного работника и найдет работу только для этого работника. $result = $conn->query("SELECT * FROM worker where id=$worker_id");
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню