MySQL纬度和经度表设置

时间:2011-01-18 15:48:43

标签: mysql spatial latitude-longitude

我想在mysql数据库表中存储位置的纬度和经度值。考虑到未来,我希望能够在特定位置的特定半径范围内找到这些位置。话虽如此,我应该将纬度和经度值存储在哪些数据类型?请你能为我提供一个创建表脚本,如下所示:

place_id  |  lat  |  long

上表中是否有一个我缺少的专栏,它将为我提供我目前可能看不到的其他信息?

感谢您的帮助。

2 个答案:

答案 0 :(得分:21)

您应该将点存储在数据类型为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和距离的公式会更复杂。

答案 1 :(得分:0)

我通过大量的主题挖掘了几个小时,无法找到一个查询,返回半径内的点,以km为单位。 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是具有“位置”字段POINT类型的实体。 由于MySQL的param绑定问题,我无法直接使用DQL,这就是低级本机查询的原因。 rsm是将结果映射到实体对象所必需的。但是,可以没有它。

随意使用它。我希望它会为你节省一些时间。