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.645195 140.030858
ナゴヤドーム 35.185958 136.947305
ほっともっとフィールド神戸 34.680657 135.073416
マツダ Zoom-Zoom スタジアム広島 34.391784 132.483526
メットライフドーム 35.768790 139.420591
横浜スタジアム 35.443336 139.640000
楽天生命パーク宮城 38.259974 140.904462
京セラドーム大阪 34.670387 135.475066
阪神甲子園球場 34.721206 135.361621
札幌ドーム 43.014841 141.408055
東京ドーム 35.705639 139.751891
福岡 ヤフオク!ドーム 33.593835 130.363662
明治神宮野球場 35.674510 139.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を指定するということが正しい使い方のようです。

コメント