На моем сайте я пытаюсь найти места поблизости.
Я пытаюсь использовать формулу Хаверсина для этого.
Я использую следующий запрос, чтобы получить все местоположения в радиусе 25 км.
SELECT id, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) AS distance FROM shops HAVING distance < 25 ORDER BY name asc
Однако я думаю, что некоторые функции могут быть только MySQL, потому что я получаю следующую ошибку:
Предупреждение: PDOStatement :: execute () [pdostatement.execute]: SQLSTATE [42883]: Неопределенная функция: 7 ОШИБКА: функция радианов (текст) не существует LINE 1: … id, (6371 * acos (cos (радианы ( 51.8391)) * cos (radians (l … ^ HINT: никакая функция не соответствует указанному имени и типам аргументов. Возможно, вам придется добавлять явные типы приведения …
- импортировать CSV-файл в postgres через php на веб-странице
- Могу ли я получить пользовательский формат даты для сбора (списков) на Laravel5?
- Laravel localhost работает, но heroku дает 500 ошибок
- Объединение таблиц из двух баз данных с использованием codeigniter
- Соединение Postgres происходит медленно с PHP
Или, возможно, это связано с тем фактом, что я должен изменить текст lat
в моем запросе. Но я не знаю, что это должно быть.
51.8391 и 4.6265 являются длинными и латами моего «начального» пункта.
Любая помощь очень ценится, так как я не знаю, что менять 🙂
РЕДАКТИРОВАТЬ
Похоже, проблема заключается в том, где я пытаюсь сделать: radians(lat)
.
lat – столбец в моей таблице.
Когда я пытаюсь использовать rad()
поскольку hakre предположил, что ошибка изменяется: function rad(numeric) does not exist
EDIT 2
Теперь мы куда-то попадаем.
Тип данных столбцов, которые действительно заданы как текст (как предложено mu, слишком коротки).
Я изменил его на двойную точность.
Однако теперь я получаю еще одну ошибку:
Предупреждение: PDOStatement :: execute () [pdostatement.execute]: SQLSTATE [42703]: Неопределенный столбец: 7 ОШИБКА: столбец «расстояние» не существует LINE 1: … adians (lat)))) AS distance FROM stores HAVING расстояние <… ^ в …
Но я думал, что сделал псевдоним в избранном. Есть идеи?
Также, если вы, ребята, думаете, что это должно пойти по другому вопросу, просто дайте мне знать, и я закрою это.
PostgreSQL имеет функцию radians
:
radians(dp)
градусы к радианам
но radians
нужен аргумент с плавающей запятой, и вы пытаетесь дать ему какую-то строку:
Неопределенная функция: 7 ОШИБКА: функция радианов ( текст )
[…] СОВЕТ: Никакая функция не соответствует указанному имени и типам аргументов . Возможно, вам придется добавлять явные типы .
Акцент мой. По-видимому, ваши столбцы lat
и lng
представляют собой char(n)
, varchar(n)
или text
столбцы. Вы должны исправить типы столбцов для lat
и lng
как numeric
, float
или некоторые другие типы с плавающей запятой ; в то же время, вы можете вручную направить свои строки и надеяться, что у вас нет данных с разбивкой:
radians(cast(lat as double precision))
MySQL делает много неявных преобразований типов, PostgreSQL является более строгим и требует, чтобы вы точно сказали, что вы имеете в виду.
Обновление для второй проблемы : предложение HAVING
оценивается перед предложением SELECT
, поэтому псевдонимы столбцов в SELECT
обычно не доступны нигде в запросе. У вас есть пара вариантов, вы можете повторить свой большой уродливый Haversine:
SELECT id, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) AS distance FROM shops HAVING ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) < 25 ORDER BY name asc
Или используйте производную таблицу, чтобы избежать повторения:
select id, distance from ( select id, name, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) as distance from shops ) as dt where distance < 25.0 order by name asc
Преобразование в радианы тривиально:
radians(n) = n * PI / 180.0