Проблема с SQL с LEFT JOIN для поиска радиуса - PullRequest
1 голос
/ 15 сентября 2011

У меня проблемы с поиском по радиусу. У меня есть таблица с почтовыми индексами, названиями мест и географическими координатами (на основе OpenGeoDB).

Вот моя SQL-команда:

SELECT main.zc_zip,
(ACOS(
    SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
    + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
    * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
) * 6380) AS `distance`
FROM tx_sdfilmbase_geodb main
LEFT JOIN tx_sdfilmbase_geodb geo ON geo.zc_location_name LIKE '%frauenfeld%'
WHERE
(ACOS(
SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
    + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
    * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
    ) * 6380) < 20
    AND main.disabled=0
ORDER BY `distance` ASC

Я получаю результаты для всех мест вокруг Фрауэнфельда в радиусе 20 километров. Тем не менее, я не получаю никакого результата для местоположений с именем «frauenfeld» - то есть я получаю все окружающие места, но не сам поиск.

Как мне изменить SQL, чтобы получить само место? Я пробовал разные вещи, но всегда один и тот же результат ...

Был бы рад некоторым подсказкам.

Greets Stefan

Изменить, чтобы ответить на комментарии ypercube и Мэтта Гибсона:

На данный момент все записи в таблице базы данных отключены = 0.

Среди многих других я получаю следующие результаты (zip, distance):

  • 8552 3,7661608052471
  • 8500 4.184731709915
  • 8523 4.9298917004071
  • 9548 4.9771821340396

Почтовые индексы для Frauenfeld: 8500, 8501, 8502 и 8503.

Отсутствующие записи в результате будут (почтовый индекс, расстояние):

  • 8500 0
  • 8501 0
  • 8502 0
  • 8503 0

Однако данные в базе геоданных верны (zip, место, широта, долгота):

  • 8503 Фрауэнфельд 47,557707 8,897367
  • 8502 Фрауэнфельд 47,557707 8,897367
  • 8501 Frauenfeld 47,557707 8,897367
  • 8500 Фрауэнфельд 47.557707 8.897367

Изменить, чтобы ответить на ответ куру куру па:

Спасибо за ваш ответ!
Ответ теперь выглядит следующим образом (zc_location_name, zc_zip, отключено, расстояние):

Frauenfeld 8500 0 NULL  
Frauenfeld 8503 0 NULL  
Frauenfeld 8502 0 NULL  
Frauenfeld 8501 0 NULL  
Gerlikon 8500 0 4.18473170991499  

Почему это NULL, а не 0? Есть догадки? :-) Кстати: каждый результат был указан 4 раза (я только что опубликовал каждый раз).

Ответы [ 3 ]

1 голос
/ 15 сентября 2011

Запустите этот запрос:

SELECT
main.zc_zip,
main.disabled,
(ACOS(
    SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
    + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
    * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
) * 6380) AS `distance`
FROM tx_sdfilmbase_geodb main
LEFT JOIN tx_sdfilmbase_geodb geo ON geo.zc_location_name LIKE '%frauenfeld%'
WHERE main.zc_zip in(8500, 8501, 8502, 8503)
ORDER BY `distance` ASC

, а затем оцените результаты distance и disabled.Ваше значение вашей функции или отключенного, вероятно, не соответствует ожидаемому.

РЕДАКТИРОВАТЬ (в ответ на нулевой результат для поля расстояния)

SELECT
main.zc_zip,
main.disabled,
(ACOS(
    SIN(RADIANS(isnull(main.zc_lat,0))) * SIN(RADIANS(isnull(geo.zc_lat,0)))
    + COS(RADIANS(isnull(main.zc_lat,0))) * COS(RADIANS(isnull(geo.zc_lat,0)))
    * COS(RADIANS(isnull(main.zc_lon,0)) - RADIANS(isnull(geo.zc_lon,0)))
) * 6380) AS `distance`
FROM tx_sdfilmbase_geodb main
LEFT JOIN tx_sdfilmbase_geodb geo ON geo.zc_location_name LIKE '%frauenfeld%'
WHERE main.zc_zip in(8500, 8501, 8502, 8503)
ORDER BY `distance` ASC

ИЛИ

SELECT
main.zc_zip,
main.disabled,
isnull(
(ACOS(
    SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
    + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
    * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
)
,0) * 6380) AS `distance`
FROM tx_sdfilmbase_geodb main
LEFT JOIN tx_sdfilmbase_geodb geo ON geo.zc_location_name LIKE '%frauenfeld%'
WHERE main.zc_zip in(8500, 8501, 8502, 8503)
ORDER BY `distance` ASC

ИЛИ в качестве альтернативы использованию ISNULL ()

измените исходный ГДЕ, чтобы сказать «ГДЕ расстояние <20 <strong> ИЛИ значение равно нулю

0 голосов
/ 15 сентября 2011

Если у кого-нибудь когда-нибудь возникнет та же / похожая проблема, ниже окончательного решения моей первоначальной проблемы:

SELECT main.zc_zip,
IFNULL(
(ACOS(
    SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
    + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
    * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
) * 6380), 0) AS `distance`
FROM tx_sdfilmbase_geodb main
LEFT JOIN tx_sdfilmbase_geodb geo ON geo.zc_location_name LIKE '%frauenfeld%'
WHERE
IFNULL(
(ACOS(
SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
    + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
    * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
    ) * 6380), 0) < 20
    AND main.disabled=0
ORDER BY `distance` ASC

ПОМНИТЕ: IFNULL для MySQL. Если вы используете другие версии SQL, убедитесь, что вы используете правильный аналог.

0 голосов
/ 15 сентября 2011

Нет необходимости в проверках LEFT JOIN и IS NULL.

Я думаю, что изменения условия WHERE будет достаточно:

WHERE
    ( (ACOS(
          SIN(RADIANS(main.zc_lat)) * SIN(RADIANS(geo.zc_lat))
          + COS(RADIANS(main.zc_lat)) * COS(RADIANS(geo.zc_lat))
          * COS(RADIANS(main.zc_lon) - RADIANS(geo.zc_lon))
      ) * 6380) < 20
      OR main.id = geo.id                          --- the PK of the table
    )
    AND main.disabled=0

Проблема, вероятно, заключается в вычислениях, производящих что-токак ACOS(1.00000001) и получая NULL, когда основной и гео (lat, lon) равны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...