SOQL DISTANCE関数とGEOLOCATION関数

DISTANCE関数、GEOLOCATION関数とは

Spring’16からSOQLでDISTANCE関数が使用できるようになりました。

DISTANCE関数

DISTANCEは以下のような形で使用します。
DISTANCE(緯度経度or住所, GEOLOCATION, 単位)

DISTANCEの第一引数は緯度経度型または住所複合型(取引先の請求先住所など)で指定します。
第二引数はGEOLOCATION関数を使って、緯度経度を出します。
第三引数は距離の単位を指定します。
今のところ、キロ’km’かマイル’mi’のどちらかしかないそうです。
DISTANCE関数はSelect文でも、Where文でも、Order by句でも使用することが可能です。

GEOLOCATION関数

GEOLOCATION関数もセットで使用されるため、こちらも使い方を簡単に説明します。
GEOLOCATION(緯度, 経度)
こちらは緯度と経度を数値で指定して、緯度経度型を返します。

実際に使ってみる

私が野球が好きということもあり、東京駅(緯度:35.681167 経度:139.767052)から30km未満のスタジアムを取得するプログラムを作ってみます。

使用するデータ

プロ野球12球団の本拠地を以下オブジェクトで登録します。

ラベルAPI参照名データ型
球場名Nameテキスト(80)
緯度経度LatLng__c地理位置情報

登録したデータはこんな感じ

球場名緯度経度 (Latitude)緯度経度 (Longitude)
ZOZOマリンスタジアム35.645195140.030858
ナゴヤドーム35.185958136.947305
ほっともっとフィールド神戸34.680657135.073416
マツダ Zoom-Zoom スタジアム広島34.391784132.483526
メットライフドーム35.768790139.420591
横浜スタジアム35.443336139.640000
楽天生命パーク宮城38.259974140.904462
京セラドーム大阪34.670387135.475066
阪神甲子園球場34.721206135.361621
札幌ドーム43.014841141.408055
東京ドーム35.705639139.751891
福岡 ヤフオク!ドーム33.593835130.363662
明治神宮野球場35.674510139.717049

Apexコードから検索して表示

東京駅(緯度: 35.681167 経度: 139.767052)から30km未満のスタジアムを検索するプログラム

Double lat = 35.681167;
Double lng = 139.767052;
List stdList = [
Select Id, Name, DISTANCE(LatLng__c, GEOLOCATION(:lat, :lng), 'km') DIC
From Stadium__c Where DISTANCE(LatLng__c, GEOLOCATION(:lat, :lng), 'km') <= 30 Order by DISTANCE(LatLng__c, GEOLOCATION(:lat, :lng), 'km') ];
for(Stadium__c std : stdList){
    String str = std.Name + '' + std.get('DIC') + 'kmです';
    System.debug(str); 
}

出力結果

東京ドームまで3.046195687901102kmです
明治神宮野球場まで4.576767299971091kmです
ZOZOマリンスタジアムまで24.165917067639356kmです
横浜スタジアムまで28.83487176521629kmです

見事に東京駅から30km圏内のスタジアムが抽出されました。距離は細かいところまで出ますね。

注意点

  • DISTANCE関数はあくまで2地点での直線距離なので、実際のルートはヘリでも使わない限り長くなります。
  • DISTANCE関数で条件を絞り込む場合、サポートされるのはイコールなしの不等号(>または<)のみとなります。 =>や=<を使用すると、以下エラーが発生します。
    System.UnexpectedException: The DISTANCE function only supports the operators > and <. Try rewriting your query using one of those operators.
  • 距離の単位はキロかマイルしかサポートされていませんので、メートル指定したい場合は、キロに変換する必要があります(300mだったら、0.3キロに変換)
  • Order byで別名は使用できないため、上記のように距離の近い順からソートするような場合は、Select句で指定した書き方を同じように書く必要があります。ちょっと面倒。。。

補足

DISTANCE関数は住所複合型を指定することも可能です。
東京駅から住所(請求先)(BillingAddress)までの距離を取得

Select Id, Name, DISTANCE(BillingAddress, GEOLOCATION(35.681167, 139.767052), 'km') From Accountt

でも、緯度経度と住所を逆にすると使えなかったようです。

Select Id, Name, DISTANCE(GEOLOCATION(35.681167, 139.767052), BillingAddress, 'km') From Account

→このSOQLはエラー

また、住所を2つ使用することもNGでした。

Select Id, Name, DISTANCE(BillingAddress, BillingAddress, 'km') From Accountt

→このSOQLもエラー

以上のことから、第一引数には住所複合型or緯度経度型、第二引数にはGEOLOCATIONを指定するということが正しい使い方のようです。

コメント