8

それぞれの緯度と経度を含む店舗のリストを含むデータベースがあります。それで、私が入力した現在の(lat、lng)位置に基づいて、1 km、5 kmなどの半径内のアイテムのリストを取得したいですか?

アルゴリズムはどうあるべきですか?アルゴリズム自体のPHPコードが必要です。

4

3 に答える 3

32

次のクエリを使用する必要があります。

たとえば、緯度と経度を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;

km単位の検索距離が必要な場合は、上記のクエリで3959を6371に置き換えます。

次のようにすることもできます。

  1. すべての緯度と経度を選択します

  2. 次に、各レコードの距離を計算します。

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

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

そして、これもあなたを助けることができます。

于 2011-02-12T18:43:47.077 に答える
6

mysqlpostgresqlのように空間的に有効になっているデータベースを選択する必要があります。そうすれば、それらが提供するすぐに使える機能のいくつかを使用できます。それ以外の場合は、手動でこれを確認してください。

于 2011-01-10T11:20:39.043 に答える
6

2セットの座標間の距離を計算するためのPHPコードを探している場合は、距離をキロメートルで計算するように調整したクラスがあります。ただし、データベースを使用している場合は、データベースが空間計算に対応しているかどうかを調べることをお勧めします(SQL ServerとMySQLが頭から離れていることはわかっています)。

ここに、チェックアウトしたいSQLソリューションの興味深いリンクがあります。PHPでの半正矢関数のSQL呼び出しの最適化

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);
于 2011-02-11T17:38:56.337 に答える