1

ivがこの複雑なことをしなければならなかったので、しばらく時間が経ちました。私は少し困惑しています。

郵便番号を受け取り、郵便番号をキーとして、元の郵便番号からの距離を値として、入力された郵便番号の半径内の郵便番号の連想配列を返すライブラリ クラスがあります。

例:FK27DJ => 0.094146570284875

Web アプリケーションはテイクアウト レストラン ファインダーであり、入力された郵便番号に最も近い各タイプのテイクアウトを検索するクエリを実行する必要があります。

takeaway_type_id フィールドに基づいて、4 種類のテイクアウトがあります。したがって、ユーザーが自分の郵便番号を入力すると、各タイプのテイクアウトが 1 つ表示されます。これは、入力した郵便番号に最も近いタイプのテイクアウトでもあります。

そのため、ライブラリ クラスから郵便番号の配列を渡し、テイクアウト テーブルを検索して、各タイプの最寄りのテイクアウトを探す必要があります。

これは理にかなっていますか?

takeaways テーブルには、次の関連フィールドが含まれています。

id(int), takeaway_type_id(int), 郵便番号

これは単一のクエリで実行できますか? サイトはphpベースです。

4

1 に答える 1

0

はい。これは英国の郵便番号のように見えるため、郵便番号を GPS 座標 (経度と緯度) にマップする別のテーブルが必要です。ここから入手できます。http://jamiethompson.co.uk/web/2008/07/24/full-uk-postcode-database-for-free/ (他の場所にもあるかもしれません。http://www.freepostcodes.org をチェックしてください。英国/ )

次に、SQL で「選択」を実行し、2 つのテーブルを結合して、SQL で実行できる距離を計算する必要があります。「SQRT(POWER(Long1 - long2,2) + POWER(Lat1 - Lat2,2))」でおおよその距離がわかります。警告: これは行ごとに計算する必要があるため、可能な結果を​​ Long+-range、Lat+-range に制限してください。

正確な距離を取得するには、少しトリグが必要です。最近のアプリで同様の機能を使用した関数を次に示します。これを操作して機能させたり、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;
}

編集:コードサンプルの追加

テストされていないコードですが、最近のプロジェクトから編集されています。構文チェックと微調整が必​​要になりますが、アイデアは得られます。

$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);

しかし - 1 つのクエリで実行できますか: 確かに、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() です

于 2012-05-15T11:34:01.133 に答える