PHP MySQL在Lat/Lng范围内查找事件

Posted

技术标签:

【中文标题】PHP MySQL在Lat/Lng范围内查找事件【英文标题】:PHP MySQL Find event within range Lat/Lng 【发布时间】:2014-08-29 14:06:50 【问题描述】:

我有一个表,其中包含使用 mysql POINT(X,Y) as geocodedLocation 的事件和位置,我正在尝试对这些数据使用半径搜索,现在我在这里找到了答案 https://gis.stackexchange.com/questions/31628/find-points-within-a-distance-using-mysql。我以前见过这个,显然这是谷歌使用位置服务的答案

我有 2 个区域应该参加活动

Area 1 = `Array ( [0] => 51.524074 [1] => -0.1005592 )`
Area 2 = `Array ( [0] => 53.818391 [1] => -1.4714507 )`

我有一些活动

Event 1 `geocodedLocation` = POINT(-1.54907739999999, 53.8007554)
Event 2 `geocodedLocation` = POINT(-0.100559200000021, 51.524074)

是的,我知道 POINT 是错误的,但我没有构建它,我只需要使用它。

现在这是我正在运行的查询

SELECT a.*
    ,(
        3959 * acos(cos(radians(51.524074)) * cos(radians((
                        SELECT Y(`geocodedLocation`)
                        ))) * cos(radians((
                        SELECT X(`geocodedLocation`)
                        )) - radians(- 0.1005592)) + sin(radians(51.524074)) * sin(radians((
                        SELECT Y(`geocodedLocation`)
                        ))))
        ) AS distance
    ,COUNT(*) AS pagedAmount
FROM Activities a
HAVING distance < 10
ORDER BY a.startTime ASC

如您所见,我正在使用位置 Area 1,事件 Event 2 在此位置更准确一点,但由于某种原因,查询不提供 Event 2 的结果

【问题讨论】:

删除 count(*) 作为 pagedAmound 部分并交换选择 X 和选择 Y,因为您的点值是相反的,您很高兴!距离大于 168 时会显示第二个事件 它是相反的,我使用 Y 作为 Lat 和 X 只要。为什么删除计数会起作用? 【参考方案1】:

不确定你想计算什么,如果它是事件的总数,那么你必须在你的选择中放入一个子查询,但是如果你想计算返回的行数,那么有一个类似的 php 查询

$row_cnt = mysqli_num_rows($result);

如果您在一个查询中使用 have 和 count,您还需要包含 group by 子句以获得比 when 结果更多的结果

SELECT a.*
    ,(3959 * acos(cos(radians(51.524074)) * cos(radians((
                        SELECT Y(`geocodedLocation`)
                        ))) * cos(radians((
                        SELECT X(`geocodedLocation`)
                        )) - radians(- 0.1005592)) + sin(radians(51.524074)) * sin(radians((
                        SELECT Y(`geocodedLocation`)
                        ))))
        ) AS distance
    ,COUNT(*) AS pagedAmount
FROM Activities a
GROUP BY distance
HAVING distance < 200
ORDER BY a.startTime ASC;

编辑

一点点在mysql中挖掘发现点对象会将纬度和经度存储为

Point(lon, lat) 

所以像我上面做的原始订单给了你正确的距离!

【讨论】:

我正在使用的框架总是添加 count(*) 用于分页,我不会弄乱仅在其之上构建的框架。至于我尝试过你的方式,第一次距离很远,就像我从我目前的位置到英国的距离为 4976 英里...... 对不起,我的错,你的 X 和 Y 是对的,但我仍然在我的 sqlfiddle 中获得事件 2 的结果【参考方案2】:

我的一个项目中有一个类似的查询。修改为你的具体情况应该是这样的:

SELECT a.*, ( 3959 * 
             acos( cos( radians(51.524074) ) * 
                  cos( radians( (SELECT Y(`geocodedLocation`)) ) ) * 
                  cos( radians( (SELECT X(`geocodedLocation`)) ) - 
                      radians(-0.1005592) ) + sin( radians(51.524074) ) * 
                  sin( radians( (SELECT Y(`geocodedLocation`)) ) ) ) ) AS distance
FROM Activities a HAVING distance < 10 ORDER BY a.startTime

【讨论】:

以上是关于PHP MySQL在Lat/Lng范围内查找事件的主要内容,如果未能解决你的问题,请参考以下文章

使用空间点类型在 MySQL 中存储 Lat Lng 值

从 Postcode DB 获取 lat/lng 并在 PHP/MYSQL 中按最近的顺序排序

根据一个经纬度求几公里范围内的数据

从 PHP 变量中的 GeoLocation 访问用户 lat/lng

我如何知道一个 Lat,Lng 点是不是包含在一个圆圈内?

删除先前的标记并在更新的 lat lng 中添加标记