【问题标题】:Find Cities Within a Certain Distance From Address using MySQL使用 MySQL 查找距地址一定距离内的城市
【发布时间】:2018-01-17 21:30:38
【问题描述】:

大家:

我完全被这个问题所困扰。我尝试将条件添加为 WHERE 语句、SELECT 语句中的 IF 函数以及加入时的 ON 语句。这些都没有产生我想要的结果。

我需要什么:特定位置的 0.5 度纬度和 0.5 度经度范围内的城市列表。

我得到了什么:两张表 - 一张包含特定位置列表,另一张包含美国人口普查所规定的城市列表。

表 1 包括:

Location Address
City
State
Location Latitude
Location Longitude

位置数据示例:

Street              City        State  Latitude     Longitude
774 Emerson Street  Palo Alto   CA     37.44239044  -122.15956879

表 2 是美国人口普查数据,包括:

City
State
City Latitude
City Longitude

示例城市数据:

City            State Latitude     Longitude
Palo Alto       CA    37.44188309   -122.14302063
Mountain View   CA    37.38605118   -122.08385468
Sunnyvale       CA    37.36883      -122.0363496

例如,如果我在加利福尼亚州帕洛阿尔托有一个位置,我想要看起来像这样的东西:

Location        City          State
Palo Alto CA    Palo Alto     CA
Palo Alto CA    Mountain View CA
Palo Alto CA    Sunnvyale     CA

我试过了:

SELECT d.`City`
      ,d.`State`
      ,l.`City`
      ,l.`StateAbbreviation`
FROM `LocationDirectoryRevised` AS d
     LEFT JOIN
     `LatLong` AS l
     ON d.`City` = l.`City` AND d.`State` = l.`StateAbbreviation`
WHERE l.`Latitude` BETWEEN (d.`Latitude` + 0.5) AND (d.`Latitude` - 0.5)
      AND
      l.`Longitude` BETWEEN (d.`Longitude` + 0.5) AND (d.`Longitude` - 0.5);

我试过了:

SELECT d.`City`
      ,d.`State`
      ,l.`City`
      ,l.`StateAbbreviation`
FROM `LocationDirectoryRevised` AS d
     LEFT JOIN
     `LatLong` AS l
     ON l.`Latitude` BETWEEN (d.`Latitude` + 0.5) AND (d.`Latitude` - 0.5) &&     
        l.`Longitude` BETWEEN (d.`Longitude` + 0.5) AND (d.`Longitude` - 0.5)

我试过了:

SELECT d.`City`
      ,d.`State`
      ,IF((l.`Latitude` < (d.`Latitude` + 0.5)) && (l.`Latitude` > (d.`Latitude` - 0.5)) &&  (l.`Longitude` < (d.`Longitude` + 0.5)) && (l.`Longitude` > (d.`Longitude` - 0.5)), l.`City`,NULL)
      ,l.`StateAbbreviation`
FROM `LocationDirectoryRevised` AS d
     LEFT JOIN
     `LatLong` AS l
     ON d.`City` = l.`City` AND d.`State` = l.`StateAbbreviation`

但是这些并没有产生我想要的结果。我错过了什么?

谢谢。

【问题讨论】:

  • 结果有什么问题?您的查询没有任何经度限制,这可能很重要。
  • 糟糕。忘了那个。我添加了与纬度 where 语句相同的行。结果显示我有一个空表。
  • 您能否给我们几行数据,以便我们了解存储在您的数据库中的实际信息是什么?
  • 我在问题中添加了示例数据。
  • 请使用您的架构和此示例数据创建一个sqlfiddle.com

标签: mysql latitude-longitude coordinate-systems geographic-distance


【解决方案1】:

试试这个:

WHERE d.`City` = 'Seattle' AND d.`State` = 'WA'
AND
l.`Latitude` < (d.`Latitude` + 0.5) 
AND 
l.`Latitude > (d.`Latitude` - 0.5)
AND
l.`Longitude` < (d.`Longitude` + 0.5) 
AND 
`l.Longitude` > (d.`Longitude` - 0.5);

或者,这也有效:

WHERE d.`City` = 'Seattle' AND d.`State` = 'WA'
AND
l.`Latitude` BETWEEN (d.`Latitude` + 0.5) AND (d.`Latitude` - 0.5)
AND
l.`Longitude` BETWEEN (d.`Longitude` + 0.5) AND (d.`Longitude` - 0.5);

【讨论】:

  • 查看下一个答案
  • 所以我实施了第一个解决方案,因为第二个似乎对我不起作用。即便如此,我每个位置只能得到一个城市,而不是每个位置的城市列表。
  • 尝试增加距离,看看是否会返回更多城市。此外,请检查您的数据,看看是否有足够的纬度/经度组合来满足您所需的距离。我已经用我们的地理表对此进行了测试,它确实返回了数据。
【解决方案2】:

经过大量工作,我能够使用子查询找出主要部分,并对我的参数稍作调整:

SELECT `City`
      ,`StateAbbreviation`
      ,`Latitude`
      ,`Longitude`
FROM `LatLong`
WHERE `Latitude` BETWEEN (SELECT `Latitude` - 0.1
                          FROM `LocationDirectoryRevised`
                          WHERE `ID` = 1)
                      AND (SELECT `Latitude` + 0.1
                          FROM `LocationDirectoryRevised`
                          WHERE `ID` = 1)
      AND
      `Longitude` BETWEEN (SELECT `Longitude` - 0.1
                          FROM `LocationDirectoryRevised`
                          WHERE `ID` = 1)
                      AND (SELECT `Longitude` + 0.1
                          FROM `LocationDirectoryRevised`
                          WHERE `ID` = 1);

现在我必须弄清楚如何将其作为所有 660 个位置的存储过程来执行。如果需要,那将是一个不同的线程。

谢谢。

【讨论】:

    【解决方案3】:

    你可以用这个:

    drop procedure if exists getNearLocations;
    create procedure getNearLocations();
    BEGIN
    DECLARE n INT DEFAULT 0;
    DECLARE i INT DEFAULT 0;
    declare e INT default 0;
    SELECT COUNT(*) FROM LocationDirectoryRevised INTO n;
    SET i=0;
    WHILE i<n DO 
    select ID from LocationDirectoryRevised into e;
      SELECT `City`
          ,`StateAbbreviation`
          ,`Latitude`
          ,`Longitude`
    FROM `LatLong`
    WHERE `Latitude` BETWEEN (SELECT `Latitude` - 0.1
                              FROM `LocationDirectoryRevised`
                              WHERE `ID` = e)
                          AND (SELECT `Latitude` + 0.1
                              FROM `LocationDirectoryRevised`
                              WHERE `ID` = e)
          AND
          `Longitude` BETWEEN (SELECT `Longitude` - 0.1
                              FROM `LocationDirectoryRevised`
                              WHERE `ID` = e)
                          AND (SELECT `Longitude` + 0.1
                              FROM `LocationDirectoryRevised`
                              WHERE `ID` = e);
      SET i = i + 1;
    END WHILE;
    End
    

    这将遍历 660 个位置并生成您正在寻找的数据。

    但是,由于子查询的数量,这可能是一个昂贵(缓慢)的查询,但对于 660 个位置来说应该足够了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      相关资源
      最近更新 更多