0

私はここで多くの計算といくつかの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

ある種の結果 (上記のクエリに基づくものではない) を返すためにこれを書きましたが、1 つの郵便番号しか除外されません。

## 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 では、USER SUBMITTED ZIP CODE とユーザーがマイルで送信した DISTANCE から郵便番号を配列にプッシュするにはどうすればよいでしょうか。円の代わりに四角形にすることもできますが、機能にとってそれほど重要ではありません。速いほど良いです。

4

3 に答える 3

5

質問の小さいながらも重要な部分に取り組みます。

ただし、 b.zip_code が実際に何であるかを見つけることも理解することもできません! (「b.」と「zips a、zips b」は何ですか?)

基本的に、クエリは 2 つのテーブルを結合します。しかし、結合されている両方のテーブルは実際には同じテーブル - 「zip」です (つまり、「zip」テーブルをそれ自体に結合します)。 「zips」テーブルの最初のコピーと、「zips」テーブルの 2 番目のコピーでは、各コピーにテーブル エイリアスを指定しています。つまり、「a」と「b」です。

したがって、「b.xxx」は、「結合されているそのテーブルの 2 番目のインスタンスから、テーブル zip の列 xxx」を意味します。

于 2011-02-28T16:12:04.010 に答える
3

最初のクエリの何が問題なのかわかりません。データベースに緯度と経度があります (私の理解では、単一のエントリを他のすべてのエントリと比較しています)。例の一部にすぎない状態を送信または返す必要はありません。最初のクエリを次のように機能させます。

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などの検索エンジンを調べる必要があります。

于 2011-02-28T16:15:41.590 に答える
0

fetchrow_arrayリスト参照のリスト、基本的には 2 次元配列を返します。ここで、各行はデータベース クエリからの異なる結果を表し、各列はクエリからのフィールドを表します (この場合、行ごとに 1 つのフィールドまたは列しかありません) )。

呼び出すwhile ($test123->fetchrow_array())と、プログラムがクエリを何度も実行するため、無限ループが発生します。クエリが結果を返す場合、while条件が満たされ、ループが繰り返されます。for my $row ($test123->fetchrow_array()) { ...通常のイディオムは、クエリを 1 回だけ実行し、結果を反復処理する のような言い方です。

各結果はリスト参照であり、関心のある郵便番号は最初の (そして唯一の) 列にあるため、次のような配列に結果を蓄積できます。

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

mapまたは、Perl のステートメントでさらに簡潔に:

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

これは同じことをします。

于 2011-02-28T16:48:52.057 に答える