MySQL - Perl: как получить массив почтовых индексов в пределах отправленных «х» миль отправленного «почтового индекса» в примере Perl

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 в запросе.

Структура my myQL SQL выглядит следующим образом:

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

Теги:
latitude-longitude
zipcode

3 ответа

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
}

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

  • 0
    Хм, спасибо У меня нет $ 1500 для Сфинкса, но мой почтовый индекс составляет 40 тыс. Строк. Я пытаюсь привести пример, который вы мне дали, основываясь на том, что я узнал здесь за последние несколько минут. Я скоро вернусь ко всем.
  • 0
    Сфинкс свободен. Поддержка - это то, что стоит денег. Есть несколько других подобных поисковых систем, но я не настолько знаком с ними
Показать ещё 7 комментариев
5

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

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

В принципе, запрос объединяет две таблицы. НО, обе соединяемые таблицы фактически представляют собой одну и ту же таблицу - "zips" (другими словами, она присоединяется к таблице "zips" для себя "). Конечно, поскольку остальная часть запроса должна понимать, когда вы обращаетесь к первая копия таблицы "zips", а когда вторая копия таблицы "zips", вы указываете псевдоним таблицы для каждой копии - "w "," a "и" b".

Итак, "b.xxx" означает "столбец xxx из заглавных букв, из экземпляра SECOND этой таблицы".

  • 0
    Ах, спасибо. Похоже, мне нужно больше читать. Исходя из того, что теперь я знаю немного больше благодаря вам, я перейду к запросу и попытаюсь визуализировать, что там происходит.
  • 0
    итак .. лат и lng в первом примере идут откуда? "a.lat-b.lat and a.lng-b.lng" Это все еще немного сбивает меня с толку. Эти значения взяты из БД? Должны ли они (и другие ссылки там) быть "a.LAT-b.LAT и a.LONG-b.LONG" ??
Показать ещё 3 комментария
0

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()

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

  • 0
    ПРОХЛАДНО! Монументальный день обучения ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню