Intereting Posts
Сочетание нескольких таблиц базы данных? Какой лучший обработчик PHP для APC Обрезаемая фатальная ошибка: объект класса __PHP_Incomplete_Class Только первое слово строки, появляющееся в форме HTML при использовании строковой ссылки Использовать RecursiveDirectoryIterator для отображения каталогов и файлов в массив? Динамическое раскрывающееся меню PHP Преобразование массива из одного в многомерный на основе значений родительского идентификатора SQL-запрос для включения определенного тега WooCommerce отображаемая переменная изображения Android: загрузка больших файлов с помощью MultipartEntity Как переопределить массив конфигурации в контроллере в CodeIgniter? Laravel Eloquent – использование идентификатора сводной таблицы в качестве внешнего ключа в другой таблице Как выполнить метод в классе из командной строки Проблема php simplexml при чтении атрибута, который имеет название «column -:» в его имени Как получить 100% покрытие кода с помощью PHPUnit

Использование формулы Хаверсина с PostgreSQL и PDO

На моем сайте я пытаюсь найти места поблизости.

Я пытаюсь использовать формулу Хаверсина для этого.

  • http://en.wikipedia.org/wiki/Haversine_formula
  • MySQL Great Circle Distance (формула Хаверсина)
  • Вычислять zipcodes в диапазоне

Я использую следующий запрос, чтобы получить все местоположения в радиусе 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: никакая функция не соответствует указанному имени и типам аргументов. Возможно, вам придется добавлять явные типы приведения …

Или, возможно, это связано с тем фактом, что я должен изменить текст 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 расстояние <… ^ в …

Но я думал, что сделал псевдоним в избранном. Есть идеи?

Также, если вы, ребята, думаете, что это должно пойти по другому вопросу, просто дайте мне знать, и я закрою это.

Related of "Использование формулы Хаверсина с PostgreSQL и PDO"

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