【问题标题】:MySQL - Perl: How to get array of zip codes within submitted "x" miles of submitted "zipcode" in Perl exampleMySQL - Perl:如何在 Perl 示例中获取提交的“x”英里内提交的“邮政编码”的邮政编码数组
【发布时间】:2011-02-28 16:01:24
【问题描述】:

我在这里找到了许多计算和一些 php 示例,大多数都只是在我的脑海中。

我找到了这个例子:

SELECT b.zip_code, b.state,
       (3956 * (2 * ASIN(SQRT(
       POWER(SIN(((a.lat-b.lat)*0.017453293)/2),2) +
       COS(a.lat*0.017453293) *
       COS(b.lat*0.017453293) *
       POWER(SIN(((a.lng-b.lng)*0.017453293)/2),2))))) AS distance
FROM zips a, zips b
WHERE
       a.zip_code = '90210' ## I would use the users submitted value
GROUP BY distance
having distance <= 5; ## I would use the users submitted value

但是,我无法理解如何使用我的数据库实现查询。

看起来该查询已满足我的所有需求。

但是,我什至无法找到/理解 b.zip_code 实际上是什么! (b.zips a, zips b 是什么?)

我也不需要查询中的state

我的mySQL db结构是这样的:

    ZIP | LAT     | LONG
  33416 | 26.6654 | -80.0929

我写这篇文章是为了返回某种结果(不是基于上面的查询),但是它只踢出一个邮政编码。

## Just for a test BUT, in reality I desire to SELECT a zip code WHERE ZIP = the users submitted zip code
## not by a submitted lat lon. I left off the $connect var, assume it's there.
my $set1 = (26.6654 - 0.20);
my $set2 = (26.6654 + 0.20);
my $set3 = (-80.0929 - 0.143);
my $set4 = (-80.0929 + 0.143);
my $test123 = $connect->prepare(qq{SELECT `ZIP` FROM `POSTAL`
WHERE `LAT` >= ? AND `LAT` <= ? 
AND `LONG` >= ? AND `LONG` <= ?})  or die "$DBI::errstr";
$test123->execute("$set1","$set2","$set3","$set4") or die "$DBI::errstr";
my $cntr;
while(@zip = $test123->fetchrow_array()) {
    print qq~$zip[$cntr]~;
    push(@zips,$zip[$cntr]);
    $cntr++;
}

如你所见,我是个新手,所以我需要一些人在这里提供详细的解释。

那么,在 Perl 中,我如何将邮政编码从用户提交的邮政编码推送到数组中,然后用户提交以英里为单位的距离。可以是正方形而不是圆形,并不是对某个功能的批评。越快越好。

【问题讨论】:

    标签: mysql perl latitude-longitude zipcode


    【解决方案1】:

    我将解决这个问题的小而关键的部分:

    但是,我什至无法找到/理解 b.zip_code 实际上是什么! (“b.”和“zips a, zips b”是什么?)

    基本上,查询连接两个表。但是,要连接的两个表实际上是同一个表 - “zips”(换句话说,它将“zips”表连接到自身“)。当然,因为查询的其余部分需要了解您何时引用“zips”表的第一个副本以及“zips”表的第二个副本时,您将为每个副本提供一个表别名 - 即“a”和“b”'。

    因此,“b.xxx”的意思是“表 zip 中的第 xxx 列,来自正在连接的表的 SECOND 实例”。

    【讨论】:

    • 啊,谢谢。看起来我应该阅读更多内容。基于现在对您的了解更多,我将重新访问查询并尝试可视化那里发生的事情。
    • so.. 第一个示例中的 lat 和 lng 来自哪里? “a.lat-b.lat 和 a.lng-b.lng” 这对我来说仍然有点混乱。这些值是从数据库中提取的吗?他们(和那里的其他参考资料)应该是“a.LAT-b.LAT and a.LONG-b.LONG”吗??
    • 来自 2 份 zips 表,是的,您在第二条评论末尾所说的完全正确
    • 我得到一个错误:不能使用字符串(“45418”)作为数组引用,而“严格引用”???? 45418 是我试过的拉链。我什至尝试使用占位符,如下例所示。我真的很努力,真的。
    【解决方案2】:

    我看不出您的第一个查询有什么问题。您的数据库中有纬度和经度(如果我理解,您正在将单个条目与所有其他条目进行比较)。您不需要提交或返回只是示例一部分的状态。使第一个查询像这样工作:

    my $query = "SELECT b.zip_code,
           (3956 * (2 * ASIN(SQRT(
           POWER(SIN(((a.lat-b.lat)*0.017453293)/2),2) +
           COS(a.lat*0.017453293) *
           COS(b.lat*0.017453293) *
           POWER(SIN(((a.lng-b.lng)*0.017453293)/2),2))))) AS distance
    FROM zips a, zips b WHERE
           a.zip_code = ? 
    GROUP BY distance having distance <= ?";
    
    my $sth = $dbh->prepare($query);
    $sth->execute( $user_submitted_zip, $user_submitted_distance );
    while( my ($zip, $distance) = $sth->fetchrow() ) ) {
         # do something
    }
    

    这不会那么快,但如果您有一个小记录集(少于 30k 行)应该没问题。如果你真的想走得更快,你应该寻找一个搜索引擎,比如Sphinx,它会为你做到这一点。

    【讨论】:

    • 嗯,谢谢。我没有 1500 美元购买 Sphinx,但是我的邮政编码 db 是 40k 行。我正在根据我在过去几分钟在这里学到的知识尝试你给我的例子。我会尽快回复大家。
    • Sphinx 是免费的。支持是要花钱的。还有一些其他类似的搜索引擎,但我对它们不太熟悉
    • @Cfreak,由于我的 zip 数据库太大,使用方形区域会更好/更快吗?如果他们得到更多的结果(走出角落),那很好。如果是这样,你能举个例子吗?这是一个乐队网站,供人们在他们所在地区寻找未来的演出,所以这里没有预算。再次感谢您的帮助。
    • 另外 40k 行可能正在推动它,但如果所有内容都被索引,它可能会足够快
    • 纬度和经度必须以圆计算。否则计算会出错。您的另一个选择是构建一个大表,该表基本上包含每个邮政编码之间的距离矩阵,但它非常大,非常快。
    【解决方案3】:

    fetchrow_array 返回列表引用列表,本质上是一个二维数组,其中每一行代表数据库查询的不同结果,每一列代表查询中的一个字段(在您的情况下,只有一个字段或列,每行)。

    调用while ($test123-&gt;fetchrow_array()) 将导致无限循环,因为您的程序会一遍又一遍地执行查询。如果查询返回结果,则满足while 条件并重复循环。通常的习惯用法是说更像for my $row ($test123-&gt;fetchrow_array()) { ...,它只会执行一次查询,然后遍历结果。

    每个结果都是一个列表引用,您感兴趣的邮政编码位于第一(也是唯一)列中,因此您可以将结果累积在一个数组中,如下所示:

    my @zips = ();    # for final results
    for my $row ($test123->fetchrow_array()) {
        push @zips, $row->[0];
    }
    

    或者更简洁地使用 Perl 的 map 声明:

    my @zips = map { $_->[0] } $test123->fetchrow_array()
    

    做同样的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 2014-10-21
      相关资源
      最近更新 更多