我有一个邮政编码MySQL数据库,其中包含每个邮政编码的纬度/经度。如何查找每个州的中心邮政编码?我会在PHP中这样做。
答案 0 :(得分:3)
假设您希望将每个邮政编码的坐标视为每个州内的等加权点,并找到最接近有效“质心”的邮政编码,您可以通过组合直接在MySQL中进行:
Google关于使用PHP,MySQL和Linux创建商店定位器的文章的Finding Locations with MySQL部分谷歌地图;以及
完整的查询是:
-- the closest ZIP code
SELECT state, z.zip_code
FROM zip_codes z JOIN (
-- the distance between the "centre of mass" and the closest ZIP code
SELECT state, c.lat, c.lon
MIN(ACOS(
COS(c.lat) * COS(RADIANS(z.lat)) * COS(RADIANS(z.lon) - c.lon)
+ SIN(c.lat) * SIN(RADIANS(z.lat))
)) min
FROM zip_codes z JOIN (
-- the "centre of mass" of each state
SELECT state,
ATAN2(
SUM(SIN(RADIANS(lat))) / COUNT(*),
SQRT(
POW(SUM(COS(RADIANS(lat)) * SIN(RADIANS(lon))) / COUNT(*), 2)
+ POW(SUM(COS(RADIANS(lat)) * COS(RADIANS(lon))) / COUNT(*), 2)
)
) AS lat,
ATAN2(
SUM(COS(RADIANS(lat)) * SIN(RADIANS(lon))) / COUNT(*),
SUM(COS(RADIANS(lat)) * COS(RADIANS(lon))) / COUNT(*)
) AS lon
FROM zip_codes
GROUP BY state
) c USING (state)
GROUP BY state
) d USING (state)
WHERE ACOS(
COS(d.lat) * COS(RADIANS(z.lat)) * COS(RADIANS(z.lon) - d.lon)
+ SIN(d.lat) * SIN(RADIANS(z.lat))
) = d.min
这可能证明非常慢,因为索引(除了state
列之外)没有多大用处,但是这又是一次性操作,因此缓存结果不应该证明问题太多了。
人口稠密地区有很多邮政编码,人口稀少的地区很少。因此,确定的“质心”可能距离地理中心有一段距离(但如果符合要求,它可能是人口中心的合理代理)。
为每个邮政编码添加合适的权重将产生合理的近似值:例如每个邮政编码覆盖的总土地面积的重量,以找到地理中心;或者通过每个邮政编码中的人口来查找实际的人口中心。
拥有 true 地理中心的唯一方法是从每个州的边界推导出质心。您可以从CloudMade Downloads站点下载合适的边界多边形的坐标。
答案 1 :(得分:2)
克服它。制作所有状态矩形。
SELECT
state,
(MAX(lat)-MIN(lat))/2 + MIN(lat) 'center_lat',
(MAX(lng)-MIN(lng))/2 + MIN(lng) 'center_lng'
FROM table
GROUP BY state
这并不完美,但除非你喜欢复杂的数学,否则这是最糟糕的情况。
编辑:我刚刚重新阅读了这个问题,意识到它不是要求中心lat / lng,而是中心拉链。检索了每个状态的大致中心纬度/经度列表后,您可以循环查找每个状态的最近的ZIP。
SELECT
zip,
ABS(lat-$center_lat) + ABS(lng-$center_lng) 'diff'
FROM table
WHERE state = $state
ORDER BY diff ASC
LIMIT 1