如何获得一个位置周围的郊区列表,然后使用MySql对其他位置重复?

如何获得一个位置周围的郊区列表,然后使用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

我使用查询a获得一个距离单个位置指定距离内的郊区列表

我尝试调整查询A以获得位置1周围的郊区列表,然后获得位置2周围的郊区列表,依此类推,我将此查询称为B。基本上,查询B与查询A的操作相同,但对每个单独的位置重复此操作。我的问题是,如何仅使用MySQL来实现这一点。对于如何做到这一点的建议,我们非常感谢

下面是我正在处理的数据示例。SqlFiddle

我试过的

查询-获取单个兴趣点周围的信息

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;