列出用户位置附近的地理位置

时间:2011-01-23 14:20:32

标签: php mysql google-maps geolocation

我有一个php webapp,允许人们通过谷歌地图api(v3)插入他们的位置。然后我将lat / lng坐标存储到我的db。

我做的另一件事是允许人们将某些事件添加到数据库,然后我使用相同的lat / lng用户将事件插入到我的数据库中。例如:

用户表:

ID    U_Name    U_Location_ID
1     test      23

活动表:

ID    E_Name    E_Location_ID
1     testevent 23

位置表:

ID    L_LAT        L_LNG        L_Name
23    40.759139    -73.979723   30 Rockefeller Plaza, New York, NY 10112, USA

我现在要做的是,向用户显示 位置附近的事件列表。

我不一定有他的确切位置,但通常只是国家和城市(并非所有访客都是填写其确切位置的注册会员)。

因此,当一个成员访问时,我使用ip来定位api,它给出了他的国家名称和城市名称。我有另一种获取国家/城市lat / lng坐标的方法,但现在当我需要向该城市/国家显示近事件时我就陷入困境。

当我说“接近”时,我希望可以设置某种直径,以千米或英里为单位,并列出该直径范围内的事件。

感谢您的帮助

5 个答案:

答案 0 :(得分:6)

这里是MySQL中适用于每个表的完整查询。请记住,lat / lon字段必须是十进制字段,除非您将丢失精度:

-- set your vars
SET @lat := $$$$$;
SET @lon := $$$$$;
SET @dist := $$$$$;

-- prepare a square in miles
SET @x1 := @lon - @dist / ABS(COS(RADIANS(@lat))*69);
SET @x2 := @lon + @dist / ABS(COS(RADIANS(@lat))*69);
SET @y1 := @lat - (@dist / 69);
SET @y2 := @lat + (@dist / 69);

SELECT  t.*, 
        3956 * 2 * ASIN(
            SQRT(
                POWER(
                    SIN(
                        (@lat - t.lat) * pi() / 180 / 2
                    ), 2
                ) +
                COS(
                    @lat * pi() / 180
                ) *
                COS(
                    t.lat * pi() / 180
                ) *
                POWER(
                    SIN(
                        (@lon - t.lon) * pi() / 180 / 2
                    ), 2
                )
            )
        ) as distance
FROM    `YourTable` t
WHERE   t.longitude BETWEEN @x1 AND @x2
AND     t.latitude BETWEEN @y1 AND @y2
HAVING  distance < @dist
ORDER BY distance
LIMIT 10;

您只需将$$$$$替换为您的值即可。 现在,如果您需要完整的说明,请参阅此slides by Alexander Rubin

只需几公里,只需将x1x2 ...替换为

-- prepare a square or in kilometers
SET @x1 := @lon - @dist / ABS(COS(RADIANS(@lat))*110);
SET @x2 := @lon + @dist / ABS(COS(RADIANS(@lat))*110);
SET @y1 := @lat - (@dist / 110);
SET @y2 := @lat + (@dist / 110);

答案 1 :(得分:1)

重要的是要注意,如果你选择Xavier的精彩答案 - 并且 - 如果你使用他的公里更改你还必须在计算中将3956 * 2更改为6371 * 2,或者你只是改变范围,而不是产生的距离。

答案 2 :(得分:0)

我真的不了解你的问题。如果你使用像MaxMind这样的地理位置数据库,你也可以到达每个城市的纬度/经度。您只需为经度和纬度选择一些增量,运行SQL查询并在视图中计算从用户位置到事件位置的距离。这并不复杂。

答案 3 :(得分:0)

您知道mysql spatial extensions吗?

答案 4 :(得分:0)

这是一个可以帮助您获得特定直径范围内的所有位置的查询。 {NUMBER OF KILOMETERS}将是直径。 $ lon AND $ lat将下注用户位置的坐标。

SELECT D.*, DEGREES(acos(cos(RADIANS(90-latitude))*cos(RADIANS(90-$lat))+sin(RADIANS(90-latitude))*sin(RADIANS(90-$lat))*cos(RADIANS(longitude-$lon))))/360*40074 AS distance FROM location_table as D HAVING distance <= {NUMBER OF KILOMETERS}