2016-05-24 4 views
1

以下は、私のpostalテーブルのレコード数です。実際、この表にはすべての都市とすべての郵便番号が含まれています。以下は郵便番号に基づいてレコードを選択し、その半径はMySQLで

id city     postalcode latitude   longitude 
1 Drogteropslagen  7705 PA  52.61666700  6.50000000 
2 Coevorden   7740 AA  52.66666700  6.75000000 
3 Emmen    7812 TN  52.78333300  6.90000000 
4 Emmer-Compascuum  7881 PZ  52.81666700  7.05000000 
5 Nieuw-Dordrecht  7885 AA  52.75000000  6.96666700 

それは郵便番号と、各企業が彼のサービスを提供することができるキロで、半径だと私companyテーブルです。

id company_name city    postalcode radius latitude  longitude 
1 A    Emmen    7812 TN  10  52.78333300 6.90000000 
2 B    Nieuw-Dordrecht 7885 AA  5  52.75000000 6.96666700 
3 C    Drogteropslagen 7705 PA  25  52.61666700 6.50000000 
4 D    Foxhol   9607 PR  0  53.16666700 6.71666700 
5 E    Westerbroek  9608 PA  15  53.18333300 6.68333300 

私は特定の郵便番号などの会社を選択したいと思います。 7740 AAは、郵便番号の領域に会社の半径を加えたものです。特定の郵便番号がcompanyテーブルに必ず存在するとは限りませんが、常にpostalテーブルに存在することに注意してください。それらの企業を選択するSQLクエリを書く方法。

+0

距離アルゴリズムで始める – Strawberry

+0

@Strawberry彼は(スマートに)既に各社の緯度と経度をキャッシュしているため、アルゴリズムは必要ありません。代わりに、彼はHavesine式を使用して距離を決定することができます。 –

+0

1つのステップのみからなるアルゴリズムを使用します。 – Strawberry

答えて

1

このアプローチでは、対象会社の単一レコードを含むサブクエリと、すべての会社を含むサブクエリとの間でCROSS JOINを実行します。このクエリでは、2つの企業間の距離をキロメートル単位で計算するためにHaversine公式が使用されます(詳細はhereを参照してください)。

このクエリは、郵便番号7740 AAの半径20km以内のすべての会社を取得するために使用します。

SELECT t2.company_name, 
    (6371 * acos(cos(radians(t1.lat1)) * cos(radians(t2.lat2)) 
    * cos(radians(t2.lng2) - radians(t1.lng1)) + sin(radians(t1.lat1)) * sin(radians(t2.lat2)))) AS distance 
FROM 
(
    SELECT p.latitude AS lat1, p.longitude AS lng1 
    FROM postal p 
    WHERE p.postalcode = '7740 AA' 
) t1 
CROSS JOIN 
(
    SELECT c.company_name, p.latitude AS lat2, p.longitude AS lng2 
    FROM company c INNER JOIN postal p 
     ON c.postalcode = p.postalcode 
) t2 
HAVING distance < 20 
+0

@Tim Biegeleisen:社内のテーブルに緯度と経度があると簡単になりますか? –

+0

@OConnorあなたの質問のデータに基づいて、私は実際には2つの別々のテーブルにその点を見ていません。しかし、あなたは今私のクエリを試すことができます。 –

+0

@TimBiegeleisen私はテーブルを分けるポイントがないので、私はlatとlonを会社と同じテーブルに入れました。混乱を避けるため、このトピックに関する新しい質問を1つのデータベーステーブルだけで追加しました。 –

0

Tim Biegeleisenの質問は、私に次のような解決策を見つけるよう促します。上記のクエリで

SELECT t2.company_name, 
     (6371 * acos(cos(radians(t1.lat1)) * cos(radians(t2.lat2)) 
     * cos(radians(t2.lng2) - radians(t1.lng1)) + sin(radians(t1.lat1)) *  
     sin(radians(t2.lat2)))) AS distance, 
     t2.radius 
FROM 
    (
    SELECT p.latitude AS lat1, p.longitude AS lng1 
    FROM postal p 
    WHERE p.postalcode = '7894 AA' 
    ) t1 
    CROSS JOIN 
    (
    SELECT c.company_name, p.latitude AS lat2, p.longitude AS lng2, 
      c.radius 
    FROM company c 
    INNER JOIN postal p 
    ON c.postalcode = p.postalcode 
    ) t2 
HAVING distance < t2.radius 

、距離はキロの固定数で(例えば20または50キロ。)と比較しませんが、動的半径(km単位)各社の。