Группировка данных столбца MySQL - PullRequest
0 голосов
/ 11 ноября 2011

При первой публикации я попытаюсь придерживаться передового опыта.

Я пытаюсь создать запрос MySQL, который измеряет местоположение пользователя (представлен в запросе как $Lat и $Lng дляширота и долгота соответственно).Запрос должен вернуть 50 станций в непосредственной близости от пользователя.

Проблема в том, что данные в моей таблице содержат местоположение каждой станции вход на станцию, и мне нужна только самая близкаявход на станцию ​​на станцию!

Это мой запрос:

SELECT id, lat, lng, station_name, routes,
  ( 3959 * acos( cos( radians($Lat) )
  * cos( radians( lat ) ) * cos( radians( lng ) -
  radians($Lng) ) + sin( radians($Lat) ) * sin( radians( lat ) ) ) )  AS distance
FROM subway_stations ORDER BY distance LIMIT 0 , 50;

Запрос Above MySQL выполняет следующее:

  1. Выбирает данные из id, lat, lng, имя_поста и маршрутов
  2. Измеряет широту и lng каждой станции вместе с данными пользователя - сохраняя эти данные как «расстояние»
  3. Возвращает50 ближайших результатов

Мне нужно сгруппировать эти результаты так, чтобы возвращалась только одна запись для каждой станции, та, которая имеет наименьшее значение в столбце расстояния, который является входом станции, ближайшим к пользователю..

Я пытался использовать GROUP BY, но мне кажется, что он неправильно реализован, так как возвращаемые результаты не были желаемыми.

Ответы [ 3 ]

0 голосов
/ 11 ноября 2011

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

  1. Добавьте group by station_name, id, lat, lng в конец вашего запроса

  2. Все поля select, которые не являются частью предложения group by, нуждаются в агрегирующей функции. Совершенно очевидно, что distance должен min(...)

  3. Я не уверен, что можно использовать предложения order и limit. Если у вас есть проблемы, снимите их (временно) и сделайте так, чтобы это работало. Для моего удобства назовите этот запрос Q1.

  4. Если предложения order by и limit использовать нельзя (поэкспериментируйте и посмотрите), то вам нужен вложенный запрос. Это будет выглядеть примерно так: select * from (...Q1...) t1 ORDER BY distance LIMIT 0,50. t1 назначил временное имя внутреннему выбору, которое фактически не используется в этом запросе, но требуется для синтаксиса.

  5. В качестве оптимизации вы можете добавить предложение having во внутренний запрос Q1. То есть добавьте HAVING distance<XXXXX, если вы знаете ограничивающее расстояние.

Обратите внимание, что шаги 3 - 5 могут не понадобиться, я не уверен насчет шага 3.

0 голосов
/ 11 ноября 2011

Возможно, вам будет проще получить ближайший вход на станцию ​​с помощью php.

На самом деле это распространенная проблема, для решения которой вам потребуется использовать подзапрос.Я предполагаю, что id это просто идентификатор строки, а не уникальный для каждой станции.

SELECT subway_stations.* FROM (
    SELECT station_name, MIN(
        ( 3959 * acos( cos( radians($Lat) ) * cos( radians( lat ) ) * 
        cos( radians( lng ) - radians($Lng) ) + sin( radians($Lat) ) * 
        sin( radians( lat ) ) ) )
    ) AS distance 
    FROM subway_stations 
    GROUP BY station_name
) AS min_distances
JOIN subway_stations ON (
    min_distances.station_name = subway_stations.station_name
    AND ( 3959 * acos( cos( radians($Lat) ) * cos( radians( lat ) ) * 
        cos( radians( lng ) - radians($Lng) ) + sin( radians($Lat) ) * 
        sin( radians( lat ) ) ) 
    ) = min_distances.distance
)

Это типичное «чистое mysql» решение вашей проблемы.Однако из-за степени вычислений, связанных с определением расстояния, вы можете: - использовать исходный запрос и получить кратчайшее расстояние для каждой станции с помощью php ИЛИ - запустить внутренний запрос, описанный выше, но вставить его результаты ввременной таблицы, затем выполните аналогичный запрос, за исключением того, что вычисленное расстояние заменяется вычисленным расстоянием от временной таблицы.

0 голосов
/ 11 ноября 2011

Если вам нужна только одна наименьшая запись для каждой станции, вам не нужно LIMIT. Просто выполните

$result = mysql_query("SELECT id, lat, lng, station_name, routes, MIN(
    ( 3959 * acos( cos( radians($Lat) ) * cos( radians( lat ) ) * 
    cos( radians( lng ) - radians($Lng) ) + sin( radians($Lat) ) * 
    sin( radians( lat ) ) ) ) AS distance )
FROM subway_stations 
GROUP BY station_name;

Это вернет только одну запись на станцию ​​с наименьшим расстоянием.

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