Как использовать внутреннее соединение в запросе mysql для вычисления радиуса с использованием данного алгоритма

#php #mysql #database

Вопрос:

У меня есть две таблицы MySQL, а именно gym_activity и gym_information. Я использовал gym_id, который находится в обеих таблицах, чтобы соединить две таблицы, создав внешние ключи. Я хочу использовать внутреннее соединение, чтобы получить широту и долготу из таблицы 2(gym_information) и использовать его для вычисления радиуса и возврата предложений, которые находятся ближе всего из таблицы gym_activity. Я использовал приведенный ниже алгоритм в запросе MySQL, но я получаю ошибку:

#1054 — Неизвестная колонка «Информация о спортзале».широта» в «списке полей»

 SELECT * FROM (
    SELECT *, 
        (
            (
                (
                    acos(
                        sin(( -42.886963699999995 * pi() / 180))
                        *
                        sin(( `gym_information.latitude` * pi() / 180))   cos(( -42.886963699999995 * pi() /180 ))
                        *
                        cos(( `gym_information.latitude` * pi() / 180)) * cos((( 147.3199527 - `gym_information.longitude`) * pi()/180)))
                ) * 180/pi()
            ) * 60 * 1.1515 * 1.609344
        )
    as distance FROM `gym_activity` JOIN gym_information ON gym_information.gym_id=gym_activity.gym_id
) markers
WHERE distance <= 150
LIMIT 15;
 

Помощь была бы признательна. Спасибо

Комментарии:

1. Удалите обратные ссылки из вашего запроса.

Ответ №1:

Возможно, этот сценарий мог бы достичь желаемых результатов (см.: https://www.movable-type.co.uk/scripts/latlong-db.html)

 <?php
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - -  */
/*  Selection of points within specified radius of given lat/lon      (c) Chris Veness 2008-2016  */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - -  */

require 'inc/dbparams.inc.php';  // defines $dsn, $username, $password
$db = new PDO($dsn, $username, $password);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

$lat = $_GET['lat']; // latitude of centre of bounding circle in degrees
$lon = $_GET['lon']; // longitude of centre of bounding circle in degrees
$rad = $_GET['rad']; // radius of bounding circle in kilometers

$R = 6371;  // earth's mean radius, km

// first-cut bounding box (in degrees)
$maxLat = $lat   rad2deg($rad/$R);
$minLat = $lat - rad2deg($rad/$R);
$maxLon = $lon   rad2deg(asin($rad/$R) / cos(deg2rad($lat)));
$minLon = $lon - rad2deg(asin($rad/$R) / cos(deg2rad($lat)));

$sql = "Select Id, Postcode, Lat, Lon,
               acos(sin(:lat)*sin(radians(Lat))   cos(:lat)*cos(radians(Lat))*cos(radians(Lon)-:lon)) * :R As D
        From (
            Select Id, Postcode, Lat, Lon
            From MyTable
            Where Lat Between :minLat And :maxLat
              And Lon Between :minLon And :maxLon
        ) As FirstCut
        Where acos(sin(:lat)*sin(radians(Lat))   cos(:lat)*cos(radians(Lat))*cos(radians(Lon)-:lon)) * :R < :rad
        Order by D";
$params = [
    'lat'    => deg2rad($lat),
    'lon'    => deg2rad($lon),
    'minLat' => $minLat,
    'minLon' => $minLon,
    'maxLat' => $maxLat,
    'maxLon' => $maxLon,
    'rad'    => $rad,
    'R'      => $R,
];
$points = $db->prepare($sql);
$points->execute($params);
?>

<html>
<table>
<? foreach ($points as $point): ?>
<tr>
    <td><?= $point->Postcode ?></td>
    <td><?= number_format($point->Lat,4) ?></td>
    <td><?= number_format($point->Lon,4) ?></td>
    <td><?= number_format($point->D,3) ?></td>
</tr>
<? endforeach ?>
</table>
</html>
 

Ответ №2:

Проблема в том, как вы использовали здесь обратные галочки:

 `gym_information.latitude`
 

Вы должны отдельно окружить имя таблицы и имя столбца:

 `gym_information`.`latitude`
 

Комментарии:

1. Это решает проблему, но теперь я получаю эту ошибку: #1060 — Дубликат имени столбца «идентификатор» У меня есть идентификатор столбца в обеих таблицах. Я просто получаю доступ к широте и долготе на основе внешнего ключа.

2. @sndp Не использовать SELECT *... . В любом случае это плохая практика, но это означает, что вы выбираете ID столбец в обеих таблицах. Перечислите столбцы, которые вы хотите, и только эти столбцы.