2016-05-24 5 views
1

Ниже приведена моя таблица postal с несколькими записями. Фактически эта таблица содержит все города и все почтовые индексы.Выберите записи на основе почтового индекса и его радиуса в MySQL

id city     postalcode latitude   longitude 
1 Drogteropslagen  7705 PA  52.61666700  6.50000000 
2 Coevorden   7740 AA  52.66666700  6.75000000 
3 Emmen    7812 TN  52.78333300  6.90000000 
4 Emmer-Compascuum  7881 PZ  52.81666700  7.05000000 
5 Nieuw-Dordrecht  7885 AA  52.75000000  6.96666700 

Ниже мой company таблица с его почтовый индекс и радиус в километрах, где каждая компания может предоставить свои услуги.

id company_name city    postalcode radius latitude  longitude 
1 A    Emmen    7812 TN  10  52.78333300 6.90000000 
2 B    Nieuw-Dordrecht 7885 AA  5  52.75000000 6.96666700 
3 C    Drogteropslagen 7705 PA  25  52.61666700 6.50000000 
4 D    Foxhol   9607 PR  0  53.16666700 6.71666700 
5 E    Westerbroek  9608 PA  15  53.18333300 6.68333300 

Я бы хотел (а) выбрать компании, которые имеют конкретный почтовый индекс, например. 7740 AA живет в зоне почтового индекса плюс радиус компании. Обратите внимание, что конкретный почтовый код может не всегда существовать в таблице company, но всегда существует в таблице postal. Как написать запрос sql, чтобы выбрать эти компании.

+0

Начать с алгоритма расстояния – Strawberry

+0

@Strawberry Нет алгоритма, потому что он (умнее) уже кэшировал широту и долготу для каждой компании. Вместо этого он может использовать формулу Хавинэна для определения расстояния. –

+0

Хорошо. Используйте алгоритм, содержащий только один шаг. – Strawberry

ответ

1

Этот подход выполняет CROSS JOIN между подзапросом, содержащим одну запись для заинтересованной компании, в отношении подзапроса, содержащего каждую компанию. Запрос использует формулу Хаверсина для вычисления расстояния между двумя компаниями в километрах (и вы можете узнать больше об этом here).

Этот запрос является тем, что вы использовали бы, чтобы получить все компании в радиусе 20 км от почтового индекса 7740 AA.

SELECT t2.company_name, 
    (6371 * acos(cos(radians(t1.lat1)) * cos(radians(t2.lat2)) 
    * cos(radians(t2.lng2) - radians(t1.lng1)) + sin(radians(t1.lat1)) * sin(radians(t2.lat2)))) AS distance 
FROM 
(
    SELECT p.latitude AS lat1, p.longitude AS lng1 
    FROM postal p 
    WHERE p.postalcode = '7740 AA' 
) t1 
CROSS JOIN 
(
    SELECT c.company_name, p.latitude AS lat2, p.longitude AS lng2 
    FROM company c INNER JOIN postal p 
     ON c.postalcode = p.postalcode 
) t2 
HAVING distance < 20 
+0

@Tim Biegeleisen: будет ли проще, если у меня будет широта и долгота в таблице компаний? –

+0

@OConnor Основываясь на данных в вашем вопросе, я даже не вижу смысла в двух отдельных таблицах. Но вы можете попробовать мой запрос. –

+0

@TimBiegeleisen Я тоже не вижу смысла разделять таблицы, поэтому я поставил lat и lon на ту же таблицу, что и компания. Предотвратите запутывание, я добавил новый вопрос, связанный с этой темой, только с одной таблицей базы данных. –

0

Запрос Тима Бигелейзена вдохновляет меня найти рабочее решение следующим образом.

SELECT t2.company_name, 
     (6371 * acos(cos(radians(t1.lat1)) * cos(radians(t2.lat2)) 
     * cos(radians(t2.lng2) - radians(t1.lng1)) + sin(radians(t1.lat1)) *  
     sin(radians(t2.lat2)))) AS distance, 
     t2.radius 
FROM 
    (
    SELECT p.latitude AS lat1, p.longitude AS lng1 
    FROM postal p 
    WHERE p.postalcode = '7894 AA' 
    ) t1 
    CROSS JOIN 
    (
    SELECT c.company_name, p.latitude AS lat2, p.longitude AS lng2, 
      c.radius 
    FROM company c 
    INNER JOIN postal p 
    ON c.postalcode = p.postalcode 
    ) t2 
HAVING distance < t2.radius 

С учетом указанных выше запроса, расстояние не будет сравнивать с фиксированным числом (например, километр 20 или 50 км.), Но с динамическим радиусом (в км.) От каждой компании.

 Смежные вопросы

  • Нет связанных вопросов^_^