我只是简单地创建一个zip_code_distances表和预计算在美国的所有42K邮编它们是彼此的20-25英里半径内之间的距离。
create table zip_code_distances
(
from_zip_code mediumint not null,
to_zip_code mediumint not null,
distance decimal(6,2) default 0.0,
primary key (from_zip_code, to_zip_code),
key (to_zip_code)
)
engine=innodb;
只包括彼此的20-25英里半径内邮编减少你需要在距离表中存储的行数从它的最大1.7十亿(42K^2) - 42K到一个更可管理的400万左右。
我从网上下载含有所有的美国官方邮编的经度和纬度以CSV格式Web上的邮编数据文件:
"00601","Adjuntas","Adjuntas","Puerto Rico","PR","787","Atlantic", 18.166, -66.7236
"00602","Aguada","Aguada","Puerto Rico","PR","787","Atlantic", 18.383, -67.1866
...
"91210","Glendale","Los Angeles","California","CA","818","Pacific", 34.1419, -118.261
"91214","La Crescenta","Los Angeles","California","CA","818","Pacific", 34.2325, -118.246
"91221","Glendale","Los Angeles","California","CA","818","Pacific", 34.1653, -118.289
...
我写了一个快速和肮脏的C#程序读取该文件,并计算
sw = new StreamWriter(path);
foreach (ZipCode fromZip in zips){
foreach (ZipCode toZip in zips)
{
if (toZip.ZipArea == fromZip.ZipArea) continue;
double dist = ZipCode.GetDistance(fromZip, toZip);
if (dist > 25) continue;
string s = string.Format("{0}|{1}|{2}", fromZip.ZipArea, toZip.ZipArea, dist);
sw.WriteLine(s);
}
}
得到的输出文件如下所示:下降25英里半径范围内,每一个邮政编码,但只有输出邮编之间的距离
from_zip_code|to_zip_code|distance
...
00601|00606|16.7042215574185
00601|00611|9.70353520976393
00601|00612|21.0815707704904
00601|00613|21.1780461311929
00601|00614|20.101431539283
...
91210|90001|11.6815708119899
91210|90002|13.3915723402714
91210|90003|12.371251171873
91210|90004|5.26634939906721
91210|90005|6.56649623829871
...
然后,我会只是这个距离数据加载到使用LOAD DATA INFILE我zip_code_distances表,然后用它来限制我的应用程序的搜索空间。
例如,如果您有其邮政编码为91210用户,他们希望找到的人是他们的10英里半径内谁,那么你现在可以简单做到以下几点:
select
p.*
from
people p
inner join
(
select
to_zip_code
from
zip_code_distances
where
from_zip_code = 91210 and distance <= 10
) search
on p.zip_code = search.to_zip_code
where
p.gender = 'F'....
希望这有助于
编辑:扩展半径到100英里,使邮政编码距离增加到3250万行。
快速性能检查邮政编码91210运行时间0.009秒。
select count(*) from zip_code_distances
count(*)
========
32589820
select
to_zip_code
from
zip_code_distances
where
from_zip_code = 91210 and distance <= 10;
0:00:00.009: Query OK
保罗,我不知道我会得到这么多不同的回答这个问题。我发现你的信息特别丰富。感谢您抽出一天的时间来提供如此详尽的解释。 – 2010-10-22 15:40:56
谢谢!很开心你喜欢。当我开始回答这个问题时,肯定会花费比我原本想要的更长的时间,但我想这就是这样工作的原因! ;) – 2010-10-22 16:07:07