2012-05-15 3 views
1

Хорошо, прошло некоторое время, так как iv пришлось сделать что-то из этой сложности, и я немного в тупике.Консультация по дистанционным запросам

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

пример: FK27DJ => +0,094146570284875

Веб-приложение является ресторан навынос искателя и мне нужно, чтобы выполнить запрос, который будет найти ближайший вынос каждого типа к введенному почтовому индексу.

Существует 4 типа вынос на основе поля takeaway_type_id. Поэтому, если пользователь вводит свой собственный почтовый индекс, им будет представлен один вынос каждого типа, который также является самым близким выносом этого типа к введенному почтовому индексу.

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

Имеет ли это смысл?

вынос таблица содержит следующие соответствующие поля:

идентификаторов (INT), takeaway_type_id (INT), почтовый индекс

Может ли это быть сделано в одном запросе? Сайт основан на php.

ответ

0

Да. Поскольку это выглядит как почтовый индекс Великобритании, вам нужна другая таблица, которая отображает почтовые индексы в координаты GPS (долгота и широта). Вы можете получить это отсюда. http://jamiethompson.co.uk/web/2008/07/24/full-uk-postcode-database-for-free/ (другие места могут также иметь его, проверьте http://www.freepostcodes.org.uk/)

Затем вам нужно сделать «выбор» в SQL, соединяя две таблицы, вычисляя расстояние, которое вы можете сделать в SQL. «SQRT (POWER (Long1 - long2,2) + POWER (Lat1 - Lat2,2))» даст вам приблизительное расстояние. ПРЕДУПРЕЖДЕНИЕ. Поскольку это нужно рассчитать для каждой строки, ограничьте возможные результаты длинным + -размерным, Lat + -range.

Чтобы получить точное расстояние, вам понадобится немного триггера. Вот функция, которую я использовал в недавнем приложении, которое делает подобное, вы должны иметь возможность массировать его для работы или даже создавать int SQL-запрос.

function CalculateDistance($Longitude1, $Latitude1, $Longitude2, $Latitude2) { 
    // Not perfect for curvature of earth on the diaganol, but it's close enough ;) 
    $LatDiff = abs($Latitude1 - $Latitude2); 
    $LongDiff = abs($Longitude1 - $Longitude2); 
    // Convert to meters - 1 deg latitude = 111.12km 
    $mLatDiff = $LatDiff * 0.11112; 
    $mLongDiff = $LongDiff * 0.11112 * cos(($Latitude1 + $Latitude2)/2); 
    // Work out difference. 
    $Diff = sqrt(($mLatDiff * $mLatDiff) + ($mLongDiff * $mLongDiff)); 
    return $Diff; 
} 

Edit: Добавление кода образца

Непроверенные код, но редактироваться из недавнего проекта. Нужна проверка синтаксиса и настройка, но дадут идею.

$UserPostcode = "AB1 2FG"; 

// Find the Long/Lat of the user (you don;t have to do this, but it saves a lot of DB stress) 
// Postcodes is the table that links users to postcodes 
$sql = 'SELECT long, lat FROM postcodes WHERE postcode="' . mysql_real_escape_string($UserPostcode) .'"'; 
// ... Missing a few lines of check row exists, error reporting etc 
$UserLat = $row['lat']; 
$UserLong = $row['long']; 

// Next, come up with an acceptable range so as not to over-stress the DB: 
// What are the acceptable limits? 
// 1 deg latitude = 111.12km 
// LATITUDE: 1km = 1/111.2 degrees of latitude = 0.0089992800575953923686105111591073 
// LONGITUDE: 1km = 1/(111.2 * cos(LATITUDE)) 

$RangeLat = 8 * 1/111.2; // For 8km = 5 miles. Work out what you want here, the larger = more DB stress 
$RangeLong = 8 * 1/(111.2 * cos(deg2rad($UserLat)); // For 8km = 5 miles. Work out what you want here, the larger = more DB stress 

// Now the query you want. 
// You'll need to change this to get restauants by group, but this gives you the essence of what you need: 

$sql = 'SELECT r.restaurant_id, r.OtherDetails, r.postcode, 
        p.lat, p.long, 
        SQRT(POWER(p.lat-'.$UserLat.',2) + POWER(p.long-'.$UserLong.',2)) AS distance 
      FROM resturants r 
      LEFT JOIN postcodes p ON r.postcode=p.postcode 
      WHERE p.lat >='.($UserLat - $RangeLat).' AND p.lat <='.($UserLat + $RangeLat).' AND p.long>='.($UserLong-$RangeLong).' AND p.long>='.($UserLong+$RangeLong).' 
      ORDER BY SQRT(POWER(p.lat-'.$UserLat.',2) + POWER(p.long-'.$UserLong.',2)) ASC'; 
if (!$result = mysql_query($sql)) { ExitError(4, $sql . '<br />' . mysql_error()); } 
while ($row = mysql_fetch_assoc($result)) { 
     // This is where you can count the 4 in each category, and disregard if you get more that 4. 
     // If you get less than 4, offer to expand the range - or stick in a loop and do it automatically. 

     // Also for efficienty, I'd suggest you remove the "distance" calculation from the SQL and use the function above 
     // The function above it more accurate as it users cosine. Then simply sort by distance here instead on in SQL. 

     // Also note the above function is written for the northern hemisphere. Also won't work across the date line ;) 
     // But that shouldn't be a worry. 

} 
mysql_free_result($result); 

Но - это может быть сделано в одном запросе: Конечно, если вы хотите, чтобы сбить SQL сервер

Опять же, не проверял, но даст вам суть того, что делать. Я настоятельно рекомендую против этого, хотя!

$sql = 'SELECT r.restaurant_id, r.OtherDetails, r.postcode, 
        p.lat, p.long, 
        SQRT(POWER(p.lat-p2.lat,2) + POWER(p.long-p2.long,2)) AS distance 
      FROM resturants r 
      LEFT JOIN postcodes p ON r.postcode=p.postcode 
      LEFT JOIN postcodes p2 ON p2.postcode="' . mysql_real_escape_string($UserPostcode) .'" 
      ORDER BY SQRT(POWER(p.lat-p2.lat,2) + POWER(p.long-p2.long,2)) ASC'; 

// Если идти по этому пути, и вы хотите, убер-точности, я дам вам работу, как получить COS там :).Функции mySQL, которые вам нужны, - это RADIANS() и COS()

+0

Вы полностью недопонимаете вопрос, который класс получает предоставленный пользователем почтовый индекс - например, «KY12 3RT» - выполняет поиск в базе данных для почтовых индексов в пределах определенного радиуса, возвращая элементы из базы данных вместе с вычисленным «расстоянием от предоставленного почтового индекса» в одном массиве. Сама таблица почтовых индексов содержит долготу и широту каждого почтового индекса. – user794846

+0

Мне нужно выполнить поиск таблицы takeaways на основе почтовых индексов в массиве из класса и вернуть 4 отдельных ближайших вылета каждого типа. – user794846

+0

Основываясь на ваших комментариях, я полностью понял вопрос ... он будет делать именно то, что вы просите. Если вы не хотите, чтобы я написал код? – Robbie