Я пытаюсь выполнить геопространственный поиск в php-приложении. В настоящее время я использую следующий запрос, чтобы найти точки в пределах 10 км от заданной широты и долготы:
SELECT * FROM ( SELECT *, (6378.1 * ACOS( COS(RADIANS(48.856614)) * COS(RADIANS(latitude)) * COS(RADIANS(2.3522219) - RADIANS(longitude)) + SIN(RADIANS(48.856614)) * SIN(RADIANS(latitude))) ) AS distance FROM `destinations_info` WHERE latitude BETWEEN 48.856614 - (10 / 69) AND 48.856614 + (10 / 69) AND longitude BETWEEN 2.3522219 - (10 / (69 * COS(RADIANS(48.856614)))) AND 2.3522219 + (10 / (69 * COS(RADIANS(48.856614)))) ) d WHERE distance <= 10 LIMIT 1
Это прекрасно работает, поскольку я не ищу точную широту и долготу, которые хранятся в таблице POI.
Так, например, если у меня в моей таблице poi следующая запись
id name latitude longitude 1 Paris 48.856614 2.3522219000000177
И я вызываю запрос с lat = 48.856614
и long = 2.3522219000000177
Я не получу никаких результатов. Насколько я вижу, это происходит, потому что следующая операция возвращает NULL, а не 0 в mysql:
SELECT (6378.1 * acos(cos(radians(48.856614)) * cos(radians(48.856614)) * cos( radians(2.3522219) - radians(2.3522219)) + sin(radians(48.856614)) * sin(radians(48.856614))))
Выполняя то же самое в калькуляторе Chrome, я получаю 0 рад .
Есть ли что-то не так в запросе или мне нужно включить результаты NULL, используя также «OR IS NULL»,
IFNULL (…), 0) AS Distance также поможет вам обойти ошибку.
Проблема заключается в том, что acos вызывается со значением, которое не находится в диапазоне от -1 и 1, поэтому оно возвращает null.
SELECT cos(radians(48.856614)) * cos(radians(48.856614)) * cos( radians(2.3522219) - radians(2.3522219)) + sin(radians(48.856614)) * sin(radians(48.856614)) 1.0000000000000002
Кажется, это своего рода проблема округления.
Поскольку arc cos определяется только между -1 и 1, вы, вероятно, должны предварительно проверить его параметр или быть готовым к тому, что он может вернуть значение null, если что-то не так с вычислением.