Сначала я должен объявить, что я крайний новичок. Я только что использовал PHP и MySQL около 4 недель. Примите мои извинения заранее, если я не правильно отформатировал этот вопрос или не использовал надлежащие условия.MySQL. Выбор неправильного значения столбца в группе. По запросу для локатора хранилища. Приложение Google Maps.
Я создаю приложение локатора магазина. Для тестирования у меня есть таблица с именем «местоположения», которая содержит данные о имени, адресе и широте/долготе для 5 различных сетей ресторанов с 1500 суммарными (локальными) записями.
У меня приложение работает нормально, как стандартный локатор хранилища, где пользователь вводит свой адрес и расстояние в милях для поиска. Приведенный ниже код правильно возвращает эти результаты при удалении оператора GROUP BY. Например, когда пользователь вводит свой адрес и расстояние для поиска, оператор SELECT возвращает ВСЕ рестораны в пределах этого расстояния просто отлично.
Мое приложение требует, чтобы было только ближайшее местонахождение каждой сети ресторанов в пределах указанного пользователем расстояния, которое будет возвращено и отображено. Я добавил оператор GROUP BY, чтобы выполнить это. Правильное количество записей возвращается с правильным именем пользователя и расстоянием от пользователя. Однако все остальные поля никогда не верны. Они кажутся случайным образом выбранными из других записей, которые находятся за пределами значения MIN. Например, первая запись возвращается для DAIRY QUEEN на расстоянии 4,38 мили - это правильно. Тем не менее, адрес, штат, город и т. Д. Для DAIRY QUEEN на 4.38 миль неверны.
Я много читал о проблемах с GROUP BY и требовании использовать INNER JOIN, возможно, для решения моей проблемы? Недавний вопрос и ответ в stackoverflow адресованы именно этому, см. MySQL Selecting wrong column value in Group By query. Все решения, которые я прочитал до сих пор, заставили бы меня использовать вычисленное расстояние в качестве ключа для выполнения JOIN, и я не понимаю, как это возможно.
Вопрос 1: Как построить инструкцию SELECT для получения желаемого результата: полная строка данных всего одна сеть ресторанов в таблице мест?
Заметки о моем коде, который не так страшно, как она выглядит, и не нужно понимать, чтобы решить мою проблему:
Формула наряжать в MIN() вычисляет расстояние в милях между адресом пользователя (в переводе к широте/долготе) и lat/lon каждой записи местоположения. Поверьте мне, это работает нормально.
ORDER BY 13 инструкция: означает ЗАКАЗАТЬ 13-м полем, указанным в SELECT, в этом случае это псевдоним «расстояние». Я упоминаю об этом, потому что я заметил, что этот синтаксис недостаточно известен.
Код, следующий за инструкцией WHERE, проверяет, находится ли адрес пользователя (в lat/lon) в поле с углами lat/lon, заданными пользователем для поиска местоположения. Это называется «ограничительной коробкой». Он используется для оптимизации времени поиска. Можно просто проверить, является ли «расстояние» < = чем расстояние ввода пользователя, но это потребует прочтения всего файла местоположений. Производственная версия будет содержать около миллиона записей. Для таблицы местоположений имеется индекс: (loc_lat, loc_lon, loc_id). Я понимаю, что использование Bounding Box в операторе WHERE ограничивает диапазон индекса, который необходимо прочитать. Вопрос 2: Является ли это так, как я его реализовал, будет ли он обработан, как я описал? Будет ли решение вопроса 1 сохранить оптимизацию?
Благодарим за вас за помощь. Я действительно всего 4 недели в mySQL и PHP, и, как вы можете видеть, в моей голове?
Мой вопрос сводится к этому. Как этот SELECT должен быть изменен, чтобы возвращать только одну запись таблицы местоположений с соответствующими полями для каждого loc_name, которое является минимальным расстоянием от входного адреса пользователя?
SELECT loc_id,loc_name,loc_address_1,loc_address_2,loc_city,
loc_state,loc_postal_code,loc_phone,loc_fax,
loc_lat,loc_lon,loc_geocoded_status,
MIN(((ACOS(SIN($lat * PI() /180) * SIN(loc_lat * PI() /180) +
COS($lat * PI() /180) * COS(loc_lat * PI() /180) *
COS(($long - loc_lon) * PI() /180)) *180/PI()) *60 * 1.1515))
AS distance
FROM locations WHERE (loc_lat between $lat1 and $lat2
AND loc_lon between $lon1 and $lon2)
AND loc_geocoded_status = 1
GROUP BY loc_name
ORDER BY 13