Spark での空間照会の実行

このトピックの例は、最もよく使用される空間処理関数を示しています。

一般的なタイプの空間照会は以下のとおりです。
  • 点列で、特定の点の特定の距離内にあるすべての点を検索します。例えば、特定の位置の特定の距離内にある病院をすべて検索します。
  • 多角形のセットで、特定の点を含むすべての多角形を検索します。例えば、特定の位置を含むすべてのリスク領域 (火災、洪水、ハリケーンなど) を検索します。
  • 点列で、特定の多角形内に含まれるすべての点を検索します。例えば、特定の地域のすべての小売店を検索します。

通常、空間処理関数には、1 つの表の空間列を参照する 1 つのパラメーターと、別の表の空間定数または空間列を参照する 2 つ目のパラメーターを指定します。

別の点に近い点の特定

単純な例として、指定の位置 (ST_Point コンストラクターを使用して構成される) の特定の距離内にある病院を見つけます。
// register the data frame  as a table
hospitalsDf.createOrReplaceTempView("hospitals")
以下の照会では、NYC の Grand Central Station から 10 km 以内にある病院のリストが戻されます。
SELECT name, city, state
FROM hospitals
WHERE ST_Distance(location, ST_Point(-77.574722, 43.146732)) < 10000.0

点を含む多角形の特定

点を含む多角形を特定する空間処理関数の例は、以下のとおりです。
  1. ST_Contains(geom1, geom2) - geom2 の値が、geom1 によって識別される多角形に完全に含まれている場合は、TRUE を戻します。
  2. ST_Within(geom1, geom2) - geom1 の値が、geom2 によって識別される多角形内にある場合は、TRUE を戻します。
  3. ST_Intersects(geom1, geom2) - geom1geom2 が、接触、クロス、相互包含など、空間でなんらかの方法で交差している場合は、TRUE を戻します。
以下の各照会では、これらの関数のいずれかを使用して、指定した点を含む郡の名前が戻されます。
SELECT NAME 
FROM counties 
WHERE 
ST_Contains(shape, ST_Point(-74.237, 42.037))

SELECT NAME
FROM counties
WHERE
ST_Within(ST_Point(-74.237, 42.037), shape)

SELECT NAME
FROM counties
WHERE
ST_Intersects(shape, ST_Point(-74.237, 42.037))

各照会により、応答 Ulster が戻されます。

多角形内の点の特定

以下の各照会では、指定した多角形にある病院が特定されます。この多角形は、事前割り当てテキスト (WKT) 表現を使用して定数として定義されています。多角形定義は、文字ストリング POLYGON と、その後に続くコンマで区切られた各頂点の x,y 座標のペアで構成されます。個々の x 値と y 値はスペースで区切られます。座標ペアのリスト全体を括弧で囲む必要があります。

SELECT name
FROM hospitals
WHERE
ST_Contains(ST_WKTToSQL('POLYGON ((-74.0 42.0, -73.0 42.0, -73.0 43.0, -74.0 43.0, -74.0 42.0))'), location)

SELECT name 
FROM hospitals 
WHERE ST_Within(location, ST_WKTToSQL('POLYGON ((-74.0 42.0, -73.0 42.0, -73.0 43.0, -74.0 43.0, -74.0 42.0))'))

SELECT name 
FROM hospitals 
WHERE ST_Intersects(location, ST_WKTToSQL('POLYGON ((-74.0 42.0, -73.0 42.0, -73.0 43.0, -74.0 43.0, -74.0 42.0))'))
各照会により、21 の病院のリストが戻されます。最初の 5 つの病院は以下のとおりです。
  1. Marshall Hospital
  2. Southwestern Medical Center
  3. Hillcrest Hospital
  4. Saint Lukes Hospital
  5. Adventist Home

空間結合を使用した多角形内の点の特定

通常の結合関数が文字または数値データを含む列の値に基づいて 2 つの表を結合できるのと同様に、空間結合関数を使用して、空間データを含む列の値に基づいて表を結合することができます。次の例では、counties 表と hospitals 表を使用します。

空間結合関数を使用して、特定の郡にある病院を検索することができます。例えば、以下の照会では、Dutchess 郡のすべての病院のリストが戻されます。
SELECT c.NAME, h.name 
FROM counties AS c, hospitals AS h 
WHERE c.NAME = 'Dutchess' 
AND ST_Intersects(c.shape, h.location)
この照会は、次の結果セットを生成します。
病院名 郡の名前
Hudson River State Hospital Dutchess
Vassar Brothers Hospital Dutchess
Bowne Hospital Dutchess
Harlem Valley State Hospital Dutchess
Matteawan State Hospital Dutchess
New York State Hospital Dutchess
Saint Francis Hospital Dutchess
United States Veterans Hospital Dutchess
別の方法として、WHERE 節の空間述部と同等の SQL JOIN ... ON 表記を使用することもできます。 例えば、以下の照会は、前の照会と同じ結果セットを生成します。
SELECT h.name, c.NAME
FROM counties AS c
JOIN hospitals AS h
ON c.NAME = 'Dutchess'
AND ST_Intersects(h.location, c.shape)
以下の照会により、特定の病院がある郡の名前が戻されます。
SELECT c.NAME, h.name
FROM hospitals AS h, counties AS c
WHERE ST_Intersects(h.location, c.shape)
AND h.name = 'Vassar Brothers Hospital'
この照会は、次の結果セットを生成します。
"Vassar Brothers Hospital", "Dutchess"

追加の述部および集約

この例では、空間結合を追加の述部および集約と併用し、ビジネス上の問題に対処します。これらの例では、引き続き病院と郡の表を使用しますが、どのタイプのデータにも同じ原則を適用できます。

この例では、郡の表内の州名で修飾することによって、New York 州の各郡内の病院に対する照会が実行されます。
SELECT c.NAME, h.name
FROM counties AS c, hospitals AS h
WHERE ST_Intersects(h.location, c.shape)
AND c.STATE_NAME='New York'
ORDER BY c.NAME, h.name
結果には、New York の 230 の病院のうち、最初の 5 つが表示されます。
病院名 郡の名前
Albany Hospital Albany
Albany Hospital for Incurables Albany
Albany Hospital Sanatorium Albany
Cohoes Memorial Hospital Albany
Saint Peters Hospital Albany
病院の表のフィールドを使用して上記の照会を書き直すことによって、同じ結果を得ることができます。
SELECT c.NAME, h.name
FROM hospitals AS h, counties AS c
WHERE ST_Intersects(h.location, c.shape)
AND h.state='NY'
ORDER BY c.NAME, h.name
以下の例は、New York の郡ごとの病院数を要約したものです。
SELECT c.NAME, COUNT(h.name) AS hospital_count
FROM counties AS c, hospitals AS h
WHERE ST_Intersects(h.location, c.shape)
AND c.STATE_NAME='New York'
GROUP BY c.NAME
これにより、以下の表に示す最初の 5 つの結果 (順序は以下のとおりとは限りません) を伴う合計 45 個の結果が生成されます。
County_name Hospital_count
Essex 3
Livingston 1
Orange 4
Herkimer 1
Queens 19
人口に対する病院数が不十分な郡を特定するには、各郡の病院当たりの人口が重要なメトリックとなる場合があります。2000 年の各郡の人口を使用して、この数値を計算することができます。
SELECT c.NAME, 
COUNT(h.name) AS hospital_count, 
c.POP2000 AS Population, 
c.POP2000/COUNT(h.name) AS people_per_hospital
FROM counties AS c, hospitals AS h
WHERE c.STATE_NAME='New York'
AND ST_Intersects(h.location, c.shape)
GROUP BY c.NAME, c.POP2000
ORDER BY people_per_hospital DESC
最初の 5 つについてのこの結果 (合計 45 レコード) が表示されます。
County_name Hospital_Count Population People_per_hospital
Bronx 9 1332650 148072
Chautauqua 1 139750 139750.0
Oswego 1 122377 122377.0
Nassau 11 1334544 121322
Queens 19 2229379 117335
病床数、病院当たりの医師の数などの追加情報がある場合、医療の可能性のより良い測度を特定することができます。

範囲照会

マッピング・アプリケーション、特に Web マッピングの一般的なユース・ケースは、長方形領域内にあるオブジェクトを選択することです。これを行うには、長方形および ST_Intersects 空間述部を表す多角形を作成します。
SELECT name
FROM hospitals
WHERE ST_Intersects(location, ST_WKTToSQL(
 'POLYGON ((-74.0 42.0, -73.0 42.0, -73.0 43.0, -74.0 43.0, -74.0 42.0))'))
同じ機能を持つ別の空間述部に EnvelopesIntersect があります。これを使用して、長方形領域と交差するエンベロープを持つオブジェクトを選択することができます。 EnvelopesIntersect は、空間列の名前、長方形の左下角および右上角を表す 4 つの Double 値をパラメーターとしてとります。この空間述部は、長方形の範囲については ST_Intersects よりも使いやすく効率的です。
SELECT name
FROM hospitals
WHERE EnvelopesIntersect(location, -74.0, 42.0, -73.0, 43.0)

この述部は、線または多角形形状のいずれかの部分が指定した範囲内にある場合に true になるため、線または多角形の部分が範囲の外側にあることがあります。通常、これはマッピング・アプリケーションでは問題になりません。マッピング・アプリケーションは、表示範囲の外側にある形状を破棄します。

Google マップ、Yahoo! 地図、Bing Maps などのプロバイダーの広く使用されている Web マッピング API を使用して Web マッピング・アプリケーションを構築する場合、マップ上にカスタム・マーカーを配置する際に使用する経度と緯度の値を指定する必要があります。この情報は、以下のような照会で取得します。
SELECT name, ST_X(location) AS longitude, ST_Y(location) AS latitude
FROM hospitals
WHERE EnvelopesIntersect(location, -74.0, 42.0, -73.0, 43.0)

距離照会

空間照会の別の一般的なタイプとして、特定の位置の指定した距離内の対象を検索する照会があります。Web マッピング・アプリケーションを使用してこのような情報を取得したことがあると思います。アプリケーションから、以下のような照会のために SQL 照会を発行することができます。
  • 店舗から 16 km (10 マイル) 以内の顧客の検索
  • 現在の位置から 500 メートル以内の ATM の検索
  • 提案された店舗の位置から 10 km 以内の競合店の検索
ここでの主要な空間処理関数は ST_Distance です。この関数は、空間値の間の距離を計算し、結果をメートルで戻します。以下の照会によって、8 つの結果が生成されます。
SELECT name
FROM hospitals
WHERE ST_Distance(location, ST_Point(-74.237, 42.037)) < 46800
ORDER BY name
結果
名前
Adventist Home
Bowne Hospital
Columbia Memorial Hospital
Firemens Home
Greene County Memorial Hospital
Hudson River State Hospital
Saint Francis Hospital
Vassar Brothers Hospital
上記と同じ照会を実行する別の方法として、ST_Buffer を使用することもできます。この場合、指定の形状の周りに円形のバッファーが作成され、そのバッファー内の目的の形状が特定されます。ST_Buffer 関数は、空間形状およびこの空間値の周りのバッファーへの距離 (メートル) をパラメーターとしてとります。結果は同じです。
SELECT name
FROM hospitals
WHERE
ST_Intersects(location,
  ST_Buffer(ST_Point(-74.237, 42.037), 46800.0))
ORDER BY name
引き続き上記の例を使用して、指定した点から半径約 46800 m (30 マイル) の内の各オブジェクトへの距離をこの照会で見つけることができます。以下に、その結果を示します。
SELECT name, ST_Distance(location, ST_Point(-74.237, 42.037)) AS distance
FROM hospitals
WHERE ST_Distance(location, ST_Point(-74.237, 42.037)) < 46800.0
ORDER BY distance
名前 距離 (メートル)
Greene County Memorial Hospital 36634.88
Adventist Home 39014.09
Hudson River State Hospital 43362.54
Saint Francis Hospital 43786.58
Bowne Hospital 44319.48
Columbia Memorial Hospital 44533.58
Firemens Home 45066.09
Vassar Brothers Hospital 45525.13
または、ST_Buffer を使用して空間的な関係を計算してから、距離を特定することができます。
SELECT name, ST_Distance(location, ST_Point(-74.237, 42.037)) AS distance
FROM hospitals
WHERE
  ST_Intersects(location,
  ST_Buffer(ST_Point(-74.237, 42.037), 46800.0))
ORDER BY distance
注意が必要となる重要な違いは、このパッケージの ST_Buffer が任意の形状のバッファリングをサポートし、その方法で計算するために使用できる点です。以下の点に注意してください。
  • 大きい形状に対する ST_Buffer 照会は、高コストになる可能性があります。
  • 形状数が多い場合、ユーザーはバッファーを別々に計算し、バッファーを列に保管して、保管されたバッファーに対して操作を実行することをお勧めします。
SELECT name, ST_Distance(location, ST_WKTToSQL(
 'LINESTRING (-74.0 42.0, -73.0 42.0)'))
FROM hospitals
WHERE ST_Intersects(location, ST_Buffer(ST_WKTToSQL(
 'LINESTRING (-74.0 42.0, -73.0 42.0)'), 46800.0))
これにより 31 の結果が戻され、最初の 5 つの結果は以下のようになります。
名前 距離
Avery Hospital 38777.96
Hartford Hospital 38204.014
Springfield Municipal Hospital 39761.18
The Noble Hospital 23831.78
Hudson River State Hospital 29315.15