Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 使用WHERE子句查找距离经度和纬度范围内的POI_Mysql_Sql_Gps_Geometry_Geo - Fatal编程技术网

Mysql 使用WHERE子句查找距离经度和纬度范围内的POI

Mysql 使用WHERE子句查找距离经度和纬度范围内的POI,mysql,sql,gps,geometry,geo,Mysql,Sql,Gps,Geometry,Geo,我使用下面的sql代码来查找最接近设置坐标的“所有”poi,但我希望查找特定poi,而不是所有poi。当我尝试使用where子句时,我得到了一个错误,它不起作用,这就是我当前遇到的问题,因为我只使用一个表来表示所有poi之外的所有坐标 SET @orig_lat=55.4058; SET @orig_lon=13.7907; SET @dist=10; SELECT *, 3956 * 2 * ASIN(SQRT(POWER(SIN((@orig_lat -abs(la

我使用下面的sql代码来查找最接近设置坐标的“所有”poi,但我希望查找特定poi,而不是所有poi。当我尝试使用where子句时,我得到了一个错误,它不起作用,这就是我当前遇到的问题,因为我只使用一个表来表示所有poi之外的所有坐标

SET @orig_lat=55.4058;  
SET @orig_lon=13.7907; 
SET @dist=10;
SELECT 
    *, 
    3956 * 2 * ASIN(SQRT(POWER(SIN((@orig_lat -abs(latitude)) * pi()/180 / 2), 2) 
    + COS(@orig_lat * pi()/180 ) * COS(abs(latitude) * pi()/180) 
    * POWER(SIN((@orig_lon - longitude) * pi()/180 / 2), 2) )) as distance 
FROM geo_kulplex.sweden_bobo
HAVING distance < @dist 
ORDER BY distance limit 10;

问题在于,在本例中,不能在select或where子句中引用别名列距离。例如,您不能这样做:

select a, b, a + b as NewCol, NewCol + 1 as AnotherCol from table
where NewCol = 2
这两种情况都会失败:尝试处理NewCol+1时的select语句,以及尝试处理NewCol=2时的where语句

有两种方法可以解决此问题:

1用计算值本身替换参考值。例如:

select a, b, a + b as NewCol, a + b + 1 as AnotherCol from table
where  a + b = 2
2使用外部select语句:

select a, b, NewCol, NewCol + 1 as AnotherCol from (
    select a, b, a + b as NewCol from table
) as S
where NewCol = 2
现在,考虑到你庞大且不太人性化的专栏:我认为你应该选择最后一个选项来提高可读性:

SET @orig_lat=55.4058;  
SET @orig_lon=13.7907; 
SET @dist=10;

SELECT * FROM (
  SELECT 
    *, 
    3956 * 2 * ASIN(SQRT(POWER(SIN((@orig_lat -abs(latitude)) * pi()/180 / 2), 2) 
    + COS(@orig_lat * pi()/180 ) * COS(abs(latitude) * pi()/180) 
    * POWER(SIN((@orig_lon - longitude) * pi()/180 / 2), 2) )) as distance 
  FROM geo_kulplex.sweden_bobo
) AS S
WHERE distance < @dist
ORDER BY distance limit 10;

编辑:正如下面提到的@Kaii,这将导致完整的表扫描。根据您将要处理的数据量,您可能希望避免这种情况,并选择第一个选项,该选项应执行得更快。

在WHERE子句中不能使用别名的原因是MySQL执行操作的顺序:

从…起 哪里 分组 有 选择 订购人 执行WHERE子句时,尚未计算列别名的值。这是一件好事,因为它会浪费很多性能。设想有许多1000000行—要在WHERE子句中使用您的计算,必须首先获取并计算其中的每一行,以便WHERE条件可以将计算结果与您的预期进行比较

您可以通过以下两种方式显式执行此操作:

使用have这就是have有另一个名字作为WHERE的原因——这是一件不同的事情 使用@MostyMostacho所示的子查询将有效地以一定的开销实现同样的功能 将复杂的计算放在WHERE子句中将有效地给出与 所有这些都将执行几乎同样糟糕的操作:首先获取每一行,计算距离,最后根据距离进行过滤,然后再将结果发送给客户端

你可以得到很多!通过在HAVING子句中混合用于距离近似过滤行的简单WHERE子句和更精确的欧几里德公式,可以获得更好的性能

使用基于简单X和Y距离边界框的WHERE子句查找可以匹配@distance=10条件的行-这是一种廉价的操作。 使用HAVING子句中的欧几里德距离公式过滤这些结果-这是一个昂贵的操作。 查看此查询以理解我的意思:

SET @orig_lat=55.4058;
SET @orig_lon=13.7907; 
SET @dist=10;
SELECT 
    *, 
    3956 * 2 * ASIN(SQRT(POWER(SIN((@orig_lat -abs(latitude)) * pi()/180 / 2), 2)
    + COS(@orig_lat * pi()/180 ) * COS(abs(latitude) * pi()/180) 
    * POWER(SIN((@orig_lon - longitude) * pi()/180 / 2), 2) )) as distance 
FROM geo_kulplex.sweden_bobo
/* WHERE clause to pre-filter by distance approximation .. filter results 
   later with precise euclidian calculation. can use indexes. */
WHERE 
    /* i'm unsure about geo stuff ... i dont think you want a 
       distance of 10° here, please adjust this properly!! */
    latitude BETWEEN (@orig_lat - @dist) AND (@orig_lat + @dist)
    AND longitude BETWEEN (@orig_lon - @dist) AND (@orig_lon + @dist)
/* HAVING clause to filter result using the more precise euclidian distance */
HAVING distance < @dist 
ORDER BY distance limit 10;
对于那些对常数感兴趣的人:

3956是以英里为单位的地球半径,因此由此产生的距离以英里为单位 6371是以公里为单位的地球半径,所以用这个常数来测量以公里为单位的距离

中查找更多信息无效如何?你能在你的问题中粘贴一条错误信息吗?为了优化这种查询的速度/性能,请阅读这篇文章:你应该提到,这总是需要一个完整的表扫描,并且可能在巨大的数据集上执行不好。我将自己的答案更清楚地指出这一点。您的两种解决方案都会表现同样糟糕。没有一个索引可以用于如此复杂的计算。我已经计算出来了,我追求更快的性能,谢谢你的支持。@HenryDang很高兴听到我可以帮助你。如果您喜欢答案,请单击左侧的复选标记以接受它:-