我有一个邮政编码 MySQL 数据库,其中包含每个邮政编码的 lat/lng。如何找到每个州的中心邮政编码?我将在 PHP 中执行此操作。
问问题
1107 次
2 回答
3
假设您希望将每个邮政编码的坐标视为每个州内的同等加权点,并找到最接近有效“质心”的邮政编码,您可以通过以下组合直接在 MySQL 中完成:
谷歌关于使用 PHP、MySQL 和谷歌地图创建商店定位器的文章中的使用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
列上)不会有太大用处,但又是一次性的操作,所以缓存结果不应该证明是一个太大的问题。人口稠密地区的邮政编码较多,而人烟稀少的地区则很少。因此,确定的“质心”可能与地理中心有一段距离(但如果需要,它可能是人口中心的合理代表)。
为每个邮政编码添加适当的权重将产生合理的近似值:例如,每个邮政编码覆盖的总土地面积的权重以找到地理中心;或按每个邮政编码内的人口居民来查找实际的人口中心。
拥有一个真正的地理中心的唯一方法是从每个州的边界推导出质心。您可以从CloudMade 下载站点下载合适的边界多边形的坐标。
于 2012-10-23T17:32:58.700 回答
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
于 2012-10-23T16:51:38.547 回答