2015-07-08 6 views
5

У меня есть 2 стола, как приведенные ниже примеры, towns и things, и вам нужно получить список городов, которые располагают рядом с вещами, находящимися в пределах x Расстояние от этой записи города. Широта и долгота будут использоваться для расчета расстояния.Выберите города, у которых есть близлежащие вещи

Я смотрел на некоторые другие вопросы, и удалось получить записи из things для одного указанного города, но не могу думать, как получить список всех городов, которые имеют около things, которые находятся ближе, чем расстояние от x их.

Возможность сортировать полученные города по количеству близлежащих вещей в пределах x Расстояние будет бонусом.

TOWNS 
+--------+----------+---------+---------+ 
| townId | townName | townLat | townLng | 
+--------+----------+---------+---------+ 
|  1 | town a |  1.5 |  1.9 | 
|  2 | town b |  1.4 |  3.8 | 
|  3 | town c |  2.3 |  2.7 | 
|  4 | town d |  3.2 |  1.6 | 
| ... | ...  |  ... |  ... | 
+--------+----------+---------+---------+ 

THINGS 
+---------+-----------+----------+----------+ 
| thingId | thingName | thingLat | thingLng | 
+---------+-----------+----------+----------+ 
|  1 | thing a | 2.1  | 3.1  | 
|  2 | thing b | 1.1  | 2.3  | 
|  3 | thing c | 3.2  | 0.2  | 
|  4 | thing d | 1.3  | 1.1  | 
|  ... | ...  | ...  | ...  | 
+---------+-----------+----------+----------+ 

Заранее спасибо

+0

Большая проблема здесь будет заключаться в использовании формулы Хаверсина для определения расстояния между двумя наборами пар широты/долготы. Вы уже проделали какую-то работу над этим? –

+0

С помощью этой схемы любое решение будет очень медленным для более чем нескольких тысяч строк. Вы в основном должны рассчитать расстояние от ** каждого ** города до ** каждой ** вещи. – Vatev

+0

Пока нет - не знаю с чего начать. Я не могу понять, как применить формулу к координатам из обеих таблиц в одном запросе. – user2959229

ответ

2

Вы можете сделать CROSS JOIN получить все возможные комбинации городов и вещей, а затем вычислить расстояние Haversine между каждым городом и вещами. Я использую SELECT DISTINCT, чтобы убедиться, что город указан только один раз в результирующем наборе.

SELECT DISTINCT TOWNS.townName FROM 
TOWNS CROSS JOIN THINGS 
WHERE 3959 * acos( 
    cos(radians(TOWNS.townLat)) 
* cos(radians(THINGS.thingLat)) 
* cos(radians(TOWNS.townLng) - radians(THINGS.thingLng)) 
+ sin(radians(TOWNS.townLat)) 
* sin(radians(THINGS.thingLat)) 
) < x 

формула я использовал для x в милях (средний радиус Земли составляет 3959 миль).

+0

Это делает то, что мне нужно сейчас. Благодаря! – user2959229