MySQL - Perl: как получить массив почтовых индексов в пределах "x" миль отправленного "zipcode" в примере Perl - PullRequest
0 голосов
/ 28 февраля 2011

Я нашел много расчетов здесь и несколько примеров 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 выглядит следующим образом:

    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, как я могу вставить почтовые индексы в массив из ПОЛЬЗОВАТЕЛЬСКОГО ОТПРАВЛЕННОГО почтового индекса и отправленного пользователем DISTANCE в милях.Может быть квадратом вместо круга, на самом деле не так критично для функции.Чем быстрее, тем лучше.

Ответы [ 3 ]

5 голосов
/ 28 февраля 2011

Я рассмотрю небольшую, но важную часть вопроса:

Однако я даже не могу найти / понять, что такое b.zip_code!(что такое "b." и "zips a, zips b"?)

По сути, запрос объединяет две таблицы.НО, обе соединяемые таблицы на самом деле являются одной и той же таблицей - «zips» (другими словами, она соединяет «zips» таблицу с собой »). Конечно, поскольку остальная часть запроса должна понимать, когда вы ссылаетесь напервая копия таблицы «zips», а когда вы переходите ко второй копии таблицы «zips», вы даете псевдоним таблицы для каждой копии - wit, «a» и «b» '.

Итак, «b.xxx» означает «столбец ххх из почтовых индексов, из ВТОРОГО экземпляра этой таблицы, к которой присоединяются».

3 голосов
/ 28 февраля 2011

Я не вижу, что не так с вашим первым запросом. У вас есть широта и долгота в вашей базе данных (если я понимаю, вы сравниваете одну запись со всеми другими). Вам не нужно отправлять или возвращать состояние, которое является лишь частью примера. Сделайте так, чтобы первый запрос работал так:

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
}

Это будет не так быстро, но если у вас небольшой набор записей (менее 30 тыс. Строк), все будет хорошо. Если вы действительно хотите идти быстрее, вам следует искать поисковик, такой как Sphinx , который сделает это за вас.

0 голосов
/ 28 февраля 2011

fetchrow_array возвращает список ссылок на список, по сути двумерный массив, где каждая строка представляет отдельный результат запроса к базе данных, а каждый столбец представляет поле из запроса (в вашем случае есть только одно поле или столбец на строку).

Вызов while ($test123->fetchrow_array()) вызовет бесконечный цикл, поскольку ваша программа выполняет запрос снова и снова. Если запрос возвращает результаты, то условие while будет выполнено и цикл повторится. Обычная идиома - сказать что-то более похожее на for my $row ($test123->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()

, который делает то же самое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...