如何获得一个位置周围的郊区列表,然后使用MySql对其他位置重复?
我使用查询a获得一个距离单个位置指定距离内的郊区列表 我尝试调整查询A以获得位置1周围的郊区列表,然后获得位置2周围的郊区列表,依此类推,我将此查询称为B。基本上,查询B与查询A的操作相同,但对每个单独的位置重复此操作。我的问题是,如何仅使用MySQL来实现这一点。对于如何做到这一点的建议,我们非常感谢 下面是我正在处理的数据示例。SqlFiddle 我试过的 查询-获取单个兴趣点周围的信息如何获得一个位置周围的郊区列表,然后使用MySql对其他位置重复?,mysql,geolocation,geonames,user-variables,Mysql,Geolocation,Geonames,User Variables,我使用查询a获得一个距离单个位置指定距离内的郊区列表 我尝试调整查询A以获得位置1周围的郊区列表,然后获得位置2周围的郊区列表,依此类推,我将此查询称为B。基本上,查询B与查询A的操作相同,但对每个单独的位置重复此操作。我的问题是,如何仅使用MySQL来实现这一点。对于如何做到这一点的建议,我们非常感谢 下面是我正在处理的数据示例。SqlFiddle 我试过的 查询-获取单个兴趣点周围的信息 SELECT @lat := latitude, @lng :=longitude FROM geona
SELECT @lat := latitude, @lng :=longitude FROM geoname WHERE asciiname = 'Tamworth' and country='AU' and population>0 and fcode='PPL';
SELECT
name as suburb, 'Tamworth' as point_of_interest, country,
(
(
ACOS(SIN(@lat * PI() / 180) * SIN(latitude * PI() / 180) + COS(@lat * PI() / 180) * COS(latitude * PI() / 180) * COS((
@lng - longitude
) * PI() / 180)) * 180 / PI()
) * 60 * 1.851999999962112
) AS distance
FROM geoname
WHERE fcode='PPLX' OR fcode='PPPL'
HAVING distance <= '60'
ORDER BY distance ASC;
还有塔姆沃思周围的郊区名单
| point_of_interest | suburb | country | distance |
|-------------------|----------------------|---------|--------------------|
| Tamworth | East Tamworth | AU | 0.9548077598752538 |
| Tamworth | North Tamworth | AU | 1.4707125875055387 |
| Tamworth | West Tamworth | AU | 1.915025922482298 |
我尝试使用MySQL用户变量、GROUP_CONCAT和FIND_IN_SET创建查询B。我的想法是,我可以像使用数组一样循环遍历这些值。如果你愿意,我可以发布我的最后一次尝试,但我甚至没有接近一个解决方案,不是因为缺乏尝试
更新:这是我最后的一次尝试
SELECT @lat := GROUP_CONCAT(latitude), @lng :=GROUP_CONCAT(longitude), @city :=GROUP_CONCAT(asciiname), @area :=GROUP_CONCAT(area) FROM geoname WHERE (asciiname = 'Tamworth' or asciiname = 'Birmingham' or asciiname = 'Roanoke') and population>0 and fcode='PPL';
SELECT
FIND_IN_SET(asciiname, @city) as point_of_interest, asciiname as suburb, country,
(
(
ACOS(SIN(FIND_IN_SET(latitude, @lat) * PI() / 180) * SIN(latitude * PI() / 180) + COS(FIND_IN_SET(latitude, @lat) * PI() / 180) * COS(latitude * PI() / 180) * COS((
FIND_IN_SET(longitude, @lng) - longitude
) * PI() / 180)) * 180 / PI()
) * 60 * 1.851999999962112
) AS distance
FROM geoname
HAVING distance <= FIND_IN_SET(distance, @area)
ORDER BY distance ASC;
非常感谢您对如何使用MySQL执行此操作的建议。您只需执行自连接即可。表是SQL的一个非常基本的部分,在进一步理解这个答案之前,您真的应该仔细阅读它
SELECT poi.asciiname,
suburb.asciiname,
suburb.country,
DEGREES(
ACOS(
SIN(RADIANS( poi.latitude))
* SIN(RADIANS(suburb.latitude))
+ COS(RADIANS( poi.latitude))
* COS(RADIANS(suburb.latitude))
* COS(RADIANS(poi.longitude - suburb.longitude))
)
) * 60 * 1.852 AS distance
FROM geoname AS poi
JOIN geoname AS suburb
WHERE poi.asciiname IN ('Tamworth', 'Birmingham', 'Roanoke')
AND poi.population > 0
AND poi.fcode = 'PPL'
AND suburb.fcode IN ('PPLX', 'PPPL')
HAVING distance <= 60
ORDER BY poi.asciiname, distance
在电视上看
您会注意到,我使用MySQL的运算符作为value=a或value=B或….的缩写
您还会注意到,我使用了MySQL的和函数,而不是显式地执行这种转换
然后你将纬度分钟数乘以系数1.85199999962112,这很奇怪:它非常接近1.852,这是历史上定义为纬度分钟数的一海里的精确公里数,但奇怪的是略有不同——我想你是想用它来代替
最后,您得到了一个文本值,通过该值,您可以将结果集中的距离作为字符串进行过滤,即“60”,而这显然是一个数值,应该不带引号。您只需执行自连接即可。表是SQL的一个非常基本的部分,在进一步理解这个答案之前,您真的应该仔细阅读它
SELECT poi.asciiname,
suburb.asciiname,
suburb.country,
DEGREES(
ACOS(
SIN(RADIANS( poi.latitude))
* SIN(RADIANS(suburb.latitude))
+ COS(RADIANS( poi.latitude))
* COS(RADIANS(suburb.latitude))
* COS(RADIANS(poi.longitude - suburb.longitude))
)
) * 60 * 1.852 AS distance
FROM geoname AS poi
JOIN geoname AS suburb
WHERE poi.asciiname IN ('Tamworth', 'Birmingham', 'Roanoke')
AND poi.population > 0
AND poi.fcode = 'PPL'
AND suburb.fcode IN ('PPLX', 'PPPL')
HAVING distance <= 60
ORDER BY poi.asciiname, distance
在电视上看
您会注意到,我使用MySQL的运算符作为value=a或value=B或….的缩写
您还会注意到,我使用了MySQL的和函数,而不是显式地执行这种转换
然后你将纬度分钟数乘以系数1.85199999962112,这很奇怪:它非常接近1.852,这是历史上定义为纬度分钟数的一海里的精确公里数,但奇怪的是略有不同——我想你是想用它来代替
最后,您得到了一个文本值,通过该值可以将结果集中的距离过滤为字符串,即“60”,而这显然是一个数值,应该不加引号。。
首先,如果你有很多地理空间数据,你应该使用mysql的地理空间扩展,而不是像这样的计算。然后,您可以创建空间索引,以加快许多查询的速度,而不必像上面那样编写冗长的查询
使用与ST_距离的比较,或者创建一个具有感兴趣半径以及ST_在内的几何体,可能会得到很好的结果,并且可能比当前速度快得多。然而,ST_Dwithin是实现这一点的最好和最快的方法,它还没有在mysql中实现
这些数据类型在mysql 5.7之后就可以使用了,但是如果您使用的是旧版本,那么升级数据库是完全值得的
新的表结构。
请注意,纬度和经度字段已替换为pt,其索引已替换为单个索引
新查询A
请再次注意,我假设1度(约111公里)彼此接近。
首先,如果你有很多地理空间数据,你应该使用mysql的地理空间扩展,而不是像这样的计算。然后,您可以创建空间索引,以加快许多查询的速度,而不必像上面那样编写冗长的查询
使用与ST_距离的比较,或者创建一个具有感兴趣半径以及ST_在内的几何体,可能会得到很好的结果,并且可能比当前速度快得多。然而,ST_Dwithin是实现这一点的最好和最快的方法,它还没有在mysql中实现
这些数据类型在mysql 5.7之后就可以使用了,但是如果您使用的是旧版本,那么升级数据库是完全值得的
新的表结构。
请注意,纬度和经度字段已替换为pt,其索引已替换为单个索引
新查询A
再次注意,我假设1次逼近
距离彼此很近这是很久以前发生在tldr上的。最后,我们仍然不知道你的数据集是什么样子,也不知道你想要的结果。我已经用你提到的观点更新了这个问题。希望情况会好一点,这是tldr很久以前的事了。最后,我们仍然不知道你的数据集是什么样子,也不知道你想要的结果。我已经用你提到的观点更新了这个问题。希望情况会好一点。你为什么加入这个国家?我的意思是,从性能角度来看,限制加入候选人的数量可能是明智的,但从技术上讲,op想要一个交叉点join@Jakumi:经过深思熟虑,我认为删除我刚才在更新中所做的限制是正确的。@eggyal谢谢!!!我很高兴你问起1.8519999962112。我第一次遇到距离公式时,使用的值是不同的,无法解释。根据它应该是1.1515*1.609344或1.853159616,但在阅读了引文之后——“乘数1.1515对应于海里的旧定义,约为6080英尺。使用比例尺为10的bc,我得到:1852/3*0.3048/1760=1.1507794480”因此,1.8519999962112由1.1507794480*1导出。609344@oooooo如果答案解决了你的问题,请适当标记。@Jakumi我会及时回答的。没有必要着急。我把答案标了出来,但我还没有时间详细讨论解决方案。你为什么加入使用country?我的意思是,从性能角度来看,限制加入候选人的数量可能是明智的,但从技术上讲,op想要一个交叉点join@Jakumi:经过深思熟虑,我认为删除我刚才在更新中所做的限制是正确的。@eggyal谢谢!!!我很高兴你问起1.8519999962112。我第一次遇到距离公式时,使用的值是不同的,无法解释。根据它应该是1.1515*1.609344或1.853159616,但在阅读了引文之后——“乘数1.1515对应于海里的旧定义,约为6080英尺。使用比例尺为10的bc,我得到:1852/3*0.3048/1760=1.1507794480”因此,1.8519999962112由1.1507794480*1导出。609344@oooooo如果答案解决了你的问题,请适当标记。@Jakumi我会及时回答的。没有必要着急。我把答案标了出来,但我还没有时间详细讨论解决方案。我还没有机会测试代码,但我认为优化很有意义。如果我升级,我肯定会考虑实现类似的东西。谢谢。请注意,MySQL的空间扩展使用欧几里德几何,而问题中使用的哈弗森公式计算的是大圆距离球面几何。我还没有机会测试代码,但我认为优化很有意义。如果我升级,我肯定会考虑实现类似的东西。谢谢。注意MySQL的空间扩展使用欧几里德几何,而问题中使用的哈弗公式计算的是大圆距离球面几何。
| point_of_interest | suburb | country | distance |
|-------------------|----------------------|---------|--------------------|
| Tamworth | East Tamworth | AU | 0.9548077598752538 |
| Tamworth | North Tamworth | AU | 1.4707125875055387 |
| Tamworth | West Tamworth | AU | 1.915025922482298 |
| Birmingham | Aston | GB | 2.347111909955497 |
| Birmingham | Hockley | GB | 2.3581405942861164 |
| Birmingham | Edgbaston | GB | 2.568384753388139 |
| Roanoke | Cumberland Forest | US | 36.66226789588173 |
| Roanoke | Mountain Top Estates | US | 37.02185777044897 |
| Roanoke | Highland Park | US | 40.174566427830094 |
SELECT poi.asciiname,
suburb.asciiname,
suburb.country,
DEGREES(
ACOS(
SIN(RADIANS( poi.latitude))
* SIN(RADIANS(suburb.latitude))
+ COS(RADIANS( poi.latitude))
* COS(RADIANS(suburb.latitude))
* COS(RADIANS(poi.longitude - suburb.longitude))
)
) * 60 * 1.852 AS distance
FROM geoname AS poi
JOIN geoname AS suburb
WHERE poi.asciiname IN ('Tamworth', 'Birmingham', 'Roanoke')
AND poi.population > 0
AND poi.fcode = 'PPL'
AND suburb.fcode IN ('PPLX', 'PPPL')
HAVING distance <= 60
ORDER BY poi.asciiname, distance
CREATE TABLE `geoname2` (
`geonameid` INT(11) NOT NULL,
`asciiname` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`country` VARCHAR(2) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`pt` POINT,
`fcode` VARCHAR(10) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`population` INT(11) NULL DEFAULT NULL,
`area` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`geonameid`),
INDEX `asciiname` (`asciiname`),
INDEX `country` (`country`),
INDEX `fcode` (`fcode`),
INDEX `population` (`population`),
INDEX `area` (`area`),
SPATIAL INDEX `pt` (`pt`)
)COLLATE='utf8_unicode_ci'
ENGINE=InnoDB;
SELECT asciiname as suburb, 'Tamworth' as point_of_interest, country,
ST_DISTANCE(`pt`, POINT(@lat,@lng)) as distance
FROM geoname2
WHERE (fcode='PPLX' OR fcode='PPPL') AND ST_DISTANCE(`pt`, POINT(@lat,@lng)) <= 1
ORDER BY distance ASC;
SELECT DISTINCT g1.asciiname, g2.asciiname ,ST_DISTANCE(g1.pt, g2.pt) *111 as distance FROM geoname2 g1
INNER JOIN (SELECT `pt`, asciiname
FROM geoname2
WHERE (fcode='PPLX' OR fcode='PPPL') AND
ST_DISTANCE(`pt`, POINT(@lat,@lng)) <= 1) as g2
WHERE ST_DISTANCE(g1.pt,g2.pt) < 1
AND g1.asciiname != g2.asciiname ORDER BY distance ASC;