Это декартово произведение таблицы местоположений с собой, дважды. Поскольку запрос соединяет одну и ту же таблицу с самим собой, необходимо переименовать каждую часть, чтобы их можно было однозначно идентифицировать позже в запросе. z
, o
и a
- это имена.
Посмотрите на пример два здесь (http://www.fluffycat.com/SQL/Cartesian-Joins/), чтобы увидеть, что происходит. За исключением этого случая, вместо одного есть два декартовых произведения. Все на одной таблице.
Сам запрос потенциально может быть довольно медленным, так как он выполняет двойной декартовой продукт, он создаст временную таблицу с n³ строками и (3m) столбцами, где n - это количество строк в таблице местоположений, а m - это число столбцы.
Редактировать В ответ на комментарий. Я не уверен в этом, но после прочтения вашего запроса я считаю, что он находит все почтовые индексы, которые находятся на определенном расстоянии от другого почтового индекса. Похоже, что третий декартовой продукт (местоположения а) даже не используется, поэтому вы можете уменьшить запрос до:
SELECT o.zip_code
FROM locations z, locations o
WHERE z.zip_code = #{zip_code}
AND (3956 * (2 * ASIN(SQRT(
POWER(SIN(((z.latitude-o.latitude)*0.017453293)/2),2) +
COS(z.latitude*0.017453293) *
COS(o.latitude*0.017453293) *
POWER(SIN(((z.longitude-o.longitude)*0.017453293)/2),2)
)))) <= #{distance}
Но у этого все еще есть одно декартово произведение. Было бы лучше, если бы мы могли избавиться от этого:
SELECT zip_code
FROM locations
WHERE (3956 * (2 * ASIN(SQRT(
POWER(SIN((((SELECT latitude FROM locations WHERE zip_code = #{zip_code})-latitude)*0.017453293)/2),2) +
COS((SELECT latitude FROM locations WHERE zip_code = #{zip_code})*0.017453293) *
COS(latitude*0.017453293) *
POWER(SIN((((SELECT longitude FROM locations WHERE zip_code = #{zip_code})-longitude)*0.017453293)/2),2)
)))) <= #{distance}
Вероятно, будет очень хорошо оптимизирован MySQL