2016-06-24 2 views
1

Я использую Laravel 5.2 и имею SQL-запрос с использованием функций builder-запроса и нарушил запрос при переходе из базы данных MySQL в PostgreSQL. Запрос предназначен для получения всех местоположений в пределах определенного количества миль в широте и долготе.SQL-синтаксис в PHP Laravel Query Builder PostgreSQLvs MySQL

$locations = Location::select(
     DB::raw("*, 
      (3959 * acos(cos(radians(?)) * 
       cos(radians(lat)) 
       * cos(radians(long) - radians(?) 
       ) + sin(radians(?)) * 
       sin(radians(lat))) 
      ) AS distance")) 
     ->having("distance", "<", $distance) 
     ->orderBy("distance") 
     ->setBindings([$latitude, $longitude, $latitude]) 
     ->get(); 

После переключения на источник данных PostgreSQL, я получаю эту ошибку:

QLSTATE[42703]: Undefined column: 7 ERROR: column "distance" does not exist 
LINE 7:) AS distance from "locations" having "distance" < $4 o... 
^ (SQL: select *, 
(3959 * acos(cos(radians(37.7959362)) * 
cos(radians(lat)) 
* cos(radians(long) - radians(-122.4000032) 
) + sin(radians(37.7959362)) * 
sin(radians(lat))) 
) AS distance from "locations" having "distance" < 15 order by "distance" asc) 

Что бы быть лучшим способом решить эту проблему. Я знаю, что это разница в синтаксисе SQL между MySQL и Postgres, созданным Laravel, но я разрываю волосы, пытаясь понять, как исправить эту ошибку.

Любая помощь была бы принята с благодарностью!

ответ

1

Проблема заключается в вашей статье having. PostgreSQL не позволяет использовать производный столбец (или псевдоним столбца) в предложении having, в то время как MySQL (до тех пор, пока вы включили MySQL Extensions to Group By, который включен по умолчанию).

Одним из вариантов обойти это ограничение является использование производной таблицы, так что поле доступно для предложения having. Что-то вроде ниже (предупреждение: полностью непроверено):

$locations = Location::from(DB::raw("(select *, 
     (3959 * acos(cos(radians(?)) * 
      cos(radians(lat)) 
      * cos(radians(long) - radians(?) 
      ) + sin(radians(?)) * 
      sin(radians(lat))) 
     ) AS distance from locations) as t")) 
    ->having("distance", "<", $distance) 
    ->orderBy("distance") 
    ->setBindings([$latitude, $longitude, $latitude]) 
    ->get(); 
+0

Спасибо @patricus! Я смог получить решение, используя ваше предложение использовать производную таблицу. Мне пришлось добавить предложение group by, которое выглядело так: -> groupBy (DB :: raw ('id, title, address_1 ...')). –