mySql-查找特定城市附近的客户

时间:2019-04-30 21:35:51

标签: mysql sql

我正在尝试使用以下表格结构来查询特定城市和州X英里内的所有客户:

with open('Cool.csv', 'w') as csvFile:
    writer = csv.writer(csvFile, delimiter=';')
    for m in file: 
        message = m['msg']
        message2 = message.replace('\r\n\r\n', ';')
        message3 = message2.replace('\r\n', ';')
        entry = m['date'] + ";" + m['subject'] + ";" + message3
        list = []
        list.append(entry)
        writer.writerow(list)
csvFile.close()

Users Table
-----------
ID

PersonsName

ZipCode

如果我已经知道我感兴趣的城市的经纬度,就可以轻松找到附近的用户,如以下查询所示:

Zipcodes Table (contains all ZIPs in the US)
--------------------------------------------
ID

ZipCode

City

State

latitude

longitude

但是,我希望能够使用城市名称和州缩写来轻松输入,然后让查询使用纬度/经度进行距离比较。

我想我可以写两个查询,第一个查询获取所需城市的经纬度,然后第二个使用结果在返回的经纬度对的一定距离内找到用途,但是可以组合成一个查询,以获取适合城市匹配的经度/纬度,然后将其用于WHERE子句中的距离计算?

无法弄清楚如何制作它,以便可以找到城市的经纬度,然后在同一距离查询中使用它。

希望能够让我们的一名员工能够简单地输入e城市/州和所需的距离,并且代码返回所有适用的客户。该代码只会获得特定城市的第一个匹配项(对于较大的城市,ZIP表中可能会有很多条目),但这对我们而言很好(因此我们可以只使用第一个匹配项)。

2 个答案:

答案 0 :(得分:0)

类似的声音可能需要在其中进行地理编码,才能将城市名称转换为坐标。提供了许多优质的API(Google,Algolia,Mapbox等)

答案 1 :(得分:0)

我同意地理编码将处理此查询未涵盖的大部分边缘情况,但是如果您仅使用现有的工具寻求快速而肮脏的修复程序,我相信以下查询将为您服务。

SELECT ID from Users u
  JOIN Zipcodes z1 ON u.zipcode = z1.zipcode
  join (select latitude as desired_latitude, longitude as desired_longitude from Zipcodes limit 1 where City = '[user input]' and State = '[user input]' limit 1)
WHERE
  COS(SIN(PI()*z1.latitude/180.0)*SIN(PI()*[desired latitude]/180.0)+COS(PI()*z1.latitude/180.0)*COS(PI()*[desired latitude]/180.0)*COS(PI()*[desired longitude]/180.0-PI()*z1.longitude/180.0))*3963.0 <= [desired distance];

尽管假设您的User表中的行比Zipcodes表中的行多,但您可能希望将该查询重构为类似这样的内容:

SELECT ID from Users u
  JOIN (
          select z1.zipcode from Zipcodes z1
          join (select latitude as desired_latitude, longitude as desired_longitude from Zipcodes limit 1 where City = '[user input]' and State = '[user input]' limit 1)
          WHERE COS(SIN(PI()*z1.latitude/180.0)*SIN(PI()*desired_latitude/180.0)+COS(PI()*z1.latitude/180.0)*COS(PI()*desired_latitude/180.0)*COS(PI()*desired_longitude/180.0-PI()*z1.longitude/180.0))*3963.0 <= [desired distance]
       ) as zipsInRange ON u.zipcode = zipsInRange.zipcode;