2011-01-10 11 views
8

私は緯度と経度のある店舗のリストを持つデータベースを持っています。したがって、私が入力した現在の(緯度、経度)の場所に基づいて、1km、5kmなどの半径内のアイテムのリストを取得したいと思いますか?MySQLの空間データを使って、Google Maps上で最も近い場所を取得してください

アルゴリズムは何が必要ですか?アルゴリズム自体にPHPコードが必要です。

答えて

26

次のクエリを使用するだけで十分です。

たとえば、緯度と経度37と-122度を入力したとします。現在の緯度と経度から25マイル以内のユーザーを検索したいとします。

SELECT item1, item2, 
    (3959 * acos(cos(radians(37)) 
        * cos(radians(lat)) 
        * cos(radians(lng) 
         - radians(-122)) 
        + sin(radians(37)) 
        * sin(radians(lat)) 
       ) 
    ) AS distance 
FROM geocodeTable 
HAVING distance < 25 
ORDER BY distance LIMIT 0 , 20; 

検索距離をkmsにする場合は、上記のクエリで3959を6371に置き換えます。

また、このような操作を行うことができます。

  1. は、各レコードの距離を計算し、すべての緯度と経度

  2. を選択します。

  3. 上記のプロセスは、複数のリダイレクションで実行できます。

最適化クエリでは、ストアドプロシージャを使用できます。

およびthisもお手伝いします。

+1

この仲間の歓声 –

+0

ポイントのあるテーブルのサイズが大きくなると、これが手に入らないように少し警告します。すべてのクエリについて、テーブル内のすべてのポイントの計算が終了します。 –

+0

これにはストアドプロシージャを使用できます。 – Gaurav

6

あなたは、空間的にmysqlまたはpostgresqlのように有効になっているデータベースを選択する必要があり、その後、あなたは彼らが提供する準備ができていくつかの機能を使用することができます。 それ以外の場合は、手動でthisにチェックを入れてください。

+0

postgisqlにpostgis拡張子を付けることをお勧めします。その方法はMySQLより高速です。 – 23tux

+0

@ 23tuxそれは、より速く、はるかに完全ですが、mysqlはほとんどの人がよく知っているもので、mysql空間拡張はとても便利です –

6

2組の座標間の距離を計算するためのPHPコードを探している場合は、距離をキロメートル単位で計算するクラスを使用します。しかし、データベースを使用している場合は、データベースが空間的に計算できるかどうかを調べることをお勧めします(私はSQL ServerとMySQLが私の頭の上から外れていることを知っています)。

ここでは、チェックアウトしたいSQLソリューションの興味深いリンクを紹介します。 Optimising a haversine formula SQL call in PHP

class Distance 
{ 
    /** 
    * Mean raidus of the earth in kilometers. 
    * @var double 
    */ 
    const RADIUS = 6372.797; 

    /** 
    * Pi divided by 180 degrees. Calculated with PHP Pi constant. 
    * @var double 
    */ 
    const PI180   = 0.017453293; 

    /** 
    * Constant for converting kilometers into miles. 
    * @var double 
    */ 
    const MILES  = 0.621371192; 

    /** 
    * Calculate distance between two points of latitude and longitude. 
    * @param double $lat1 The first point of latitude. 
    * @param double $long1 The first point of longitude. 
    * @param double $lat2 The second point of latitude. 
    * @param double $long2 The second point of longitude. 
    * @param bool $kilometers Set to false to return in miles. 
    * @return double The distance in kilometers or miles, whichever selected. 
    */ 
    public static function getDistance($lat1, $long1, $lat2, $long2, $kilometers = true) 
    { 
     $lat1 *= self::PI180; 
     $long1 *= self::PI180; 
     $lat2 *= self::PI180; 
     $long2 *= self::PI180; 

     $dlat = $lat2 - $lat1; 
     $dlong = $long2 - $long1; 

     $a = sin($dlat/2) * sin($dlat/2) + cos($lat1) * cos($lat2) * sin($dlong/2) * sin($dlong/2); 
     $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); 

     $km = self::RADIUS * $c; 

     if($kilometers) 
     { 
      return $km; 
     } 
     else 
     { 
      return $km * self::MILES; 
     } 
    } 
} 

//example 
echo Distance::getDistance(40.686748, -89.555054, 40.453078, -88.939819); 
+0

私はいくつかの特別な機能をサポートするためにdatabseが必要ですか? PHPを単独で使用して直接行うことはできますか?緯度/経度座標をDBの2フィールドとして保存した場合 –

+0

私が投稿したコードは、2つの座標間の距離を示します。 –

関連する問題