Настройка таблицы широты и долготы MySQL - PullRequest
9 голосов
/ 18 января 2011

Я хочу сохранить значения широты и долготы мест в таблице базы данных mysql.Имея в виду будущее, я захочу найти эти места в пределах определенного радиуса определенного места.Сказав это, в каких типах данных я должен хранить значения широты и долготы?Пожалуйста, не могли бы вы предоставить мне сценарий создания таблицы для столбцов, например:

place_id  |  lat  |  long

Возможно, в приведенной выше таблице отсутствует столбец, который предоставит мне дополнительную информацию, которая, возможно, не будет мне нужнав настоящее время?

Спасибо за любую помощь.

Ответы [ 2 ]

21 голосов
/ 18 января 2011

Точки следует хранить в отдельном столбце с типом данных Point, который можно индексировать с помощью индекса SPATIAL (если тип таблицы MyISAM):

CREATE SPATIAL INDEX sx_place_location ON place (location)

SELECT  *
FROM    mytable
WHERE   MBRContains
               (
               LineString
                       (
                       Point($x - $radius, $y - $radius),
                       Point($x + $radius, $y + $radius)
                       )
               location
               )
        AND Distance(Point($x, $y), location) <= $radius

Это значительно повысит скорость запросов, таких как «найти все в заданном радиусе».

Обратите внимание, что лучше использовать простые TM метрические координаты (восток и север) вместо полярных (широта и долгота). Для малых радиусов они достаточно точны, а расчеты значительно упрощены. Если все ваши точки находятся в одном полушарии и находятся далеко от полюсов, вы можете использовать один центральный меридиан.

Конечно, вы все еще можете использовать полярные координаты, но формулы для вычисления MBR и расстояния будут более сложными.

0 голосов
/ 19 апреля 2016

Я провел несколько часов в тоннах тем и нигде не мог найти запрос, возвращающий точки в радиусе, определяемом км. ST_Distance_Sphere делает это, однако сервер MariaDB 5.5 не поддерживает ST_Distance_Sphere ().

Мне удалось заставить что-то работать, поэтому вот мое решение, совместимое с Doctrine 2.5 и пространственной библиотекой Doctrine CrEOF:

    $sqlPoint = sprintf('POINT(%f %f)', $lng, $lat);

    $rsm = new ResultSetMappingBuilder($this->manager);
    $rsm->addRootEntityFromClassMetadata('ApiBundle\\Entity\\Place', 'p');

    $query = $this->manager->createNativeQuery(
        'SELECT p.*, AsBinary(p.location) as location FROM place p ' .
        'WHERE (6371 * acos( cos( radians(Y(ST_GeomFromText(?))) ) ' .
        '* cos( radians( Y(p.location) ) ) * cos( radians( X(p.location) ) ' .
        '- radians(X(ST_GeomFromText(?))) ) + sin( radians(Y(ST_GeomFromText(?))) ) * sin( radians( Y(p.location) ) ) )) <= ?',
        $rsm
    );

    $query->setParameter(1, $sqlPoint, 'string');
    $query->setParameter(2, $sqlPoint, 'string');
    $query->setParameter(3, $sqlPoint, 'string');
    $query->setParameter(4, $radius, 'float');

    $result = $query->getResult();

Предполагая, что lng и lat - это XY фиксированной точки, Place - это сущность с полем «location» типа POINT. Я не мог использовать DQL напрямую из-за проблем с привязкой параметров MySQL, поэтому низкоуровневый собственный запрос. RSM требуется для отображения результатов в объектах сущности. Можно и без этого жить.

Не стесняйтесь использовать его. Надеюсь, это сэкономит вам время.

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