Kobarin's Development Blog

C#やASP.NET、公開APIなどについての記録です。

経度・緯度を持つデータを半径(m単位)で抽出する

本来であれば、座標(経度・緯度)をまず平面直角座標に変換した上で抽出するのがベストですが、精度を求められない場面でサクッとselect文を実行する方法を紹介します。
以前どこかで見ましたが、ソースを忘れたので製品SQLから引っ張ってきました。確か日本の本州限定のワザだった気がします。

「@latと@lngを中心に1000m以内のお店を抽出」する例です。

select NAME, TEL, ADDRESS
 from MYSHOP
 where sqrt(power((MyLat - @lat) * 111000, 2) + power((MyLng-@lng) * 91000, 2)) <= 1000
解説

[MyLat] [MyLng]には各々、お店の緯度・経度が入ってます。
@lat、@lngには中心座標の緯度・経度を指定します。もちろん座標数値(36.1234、138.5678等)を直接指定しても構いません。
ポイントは、緯度側の111000、経度側の91000という定数。


要は、座標を直角座標に変換する理由というのが、
「球体における位置を表している座標をそのまま使っても距離の計算ができない」
からなんです。
何故かというと、例えば、緯度の36度〜37度の間は1度。経度の137度〜138度の間は1度ですが、同じ1度でも、実は距離(メートル等)に換算すると、全く異なる長さになるのです。
わかりやすい例で言うと、経度は、赤道を1周しても360度。北極付近を1周しても360度です。でも同じ1度でも、距離が全く違います。赤道付近なら4万数千km(忘れた)、北極点ならほぼゼロですよね。
だからまずこれを
メルカトル図法(だったかな)に変換しちゃえば、距離を計算できるよね」
ってのが変換の理由です。


つまり、上記SQL文の111000と91000の意味は、
「本州だったら、1度あたり緯度なら111000を掛け、経度は91000掛ければ、まぁそこそこメートルに近い数値になるよ」
という事だったのです。「縦横の単位を合わせる」…これが正解です。
ただしあくまで東北〜九州までを同じ定数で処理するザックリ計算なので、誤差は当然あります。数m〜数十m程度あったと思います。


もし使う機会があればどうぞ。