我有一个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坐标的方法,但现在当我需要向该城市/国家显示近事件时我就陷入困境。
当我说“接近”时,我希望可以设置某种直径,以千米或英里为单位,并列出该直径范围内的事件。
感谢您的帮助
答案 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
只需几公里,只需将x1
,x2
...替换为
-- 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)
答案 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}