PostGISで最も近いジオメトリを見つける


16

私はPostGISの関数の「API」を見てきましたが、それらのほとんどが比較するために2つの要素を必要とすることに気付きました。たとえば、ST_Distance関数は、距離を見つけるために2つのジオメトリ/地理要素を取ります。

「ジオメトリGを指定して、テーブルTでG.id <> GClosest.idの最も近いジオメトリGClosestを指定してください」などの機能はありません。

PL / PgSQL関数を作成してテーブルを反復処理し、各要素でST_Distanceを呼び出すことができることを理解していますが、より良い、より効率的なソリューションがあることを望んでいます。


1
あなたは、最も近いジオメトリ、チェックまでの距離に興味がある場合gis.stackexchange.com/questions/11979/...
アンダーダーク

私が正しく理解したかどうかを教えてください...あなたは最も近いものと同じ距離を持つ次の機能が必要ですか?
falcacibar

回答:


7

質問には、レコード全体と参照ジオメトリまでの距離を返す次のような単一の(複雑ではありますが)クエリで回答することもできます。複数のレコードが最小距離に一致する場合、それらはすべて返されることに注意してください。

SELECT 
  i.*,
  md.min_distance
FROM
  address AS i, 
  (SELECT 
     ga.address_geom,
     min( ST_Distance(
            ga.address_geom,
            gb.address_geom)
        ) AS min_distance
   FROM
     address AS ga,
     address AS gb 
   WHERE 
     ga.id <> gb.id 
   AND 
     ga.id = 3
   GROUP BY 
     ga.address_geom
  ) AS md 
WHERE 
  ST_Distance( i.address_geom, md.address_geom) = md.min_distance;

アドレスのテーブルでこのクエリをテストしましたが、動作します。上記のクエリでは、id = 3のポイントに最も近いポイントを探しています。


これは良い情報です-ありがとうございます...定義によりmin(..)集約関数を理解していますが、あなたの例でそれがどのように使用されているか混乱しています。st_distance(X、Y)は2つのジオメトリタイプを取り、それらの間の距離を返します。これは単一の値です。なぜその単一の値の結果に対して集計関数を呼び出すのですか?たぶん私は...内部のselect文を誤って解釈しています
Jmoney38

group byは、結果セット全体の定数であるgaジオメトリ上にあります(gaはid = 3で選択されることに注意してください)。これは、テーブルを2回結合することなく、外部クエリのst_distancegaジオメトリを使用できるようにするためのトリックです。今日、partition句を使用することで、内部クエリを完全に回避できると考えていました。また、パフォーマンスが向上するはずです。試してみて、お知らせします。
unicoletti

残念ながら8.4でウィンドウ関数が導入されましたが、今ではpostgiとそのバージョンの両方を持つサーバーにアクセスできないため、partion句で書き換えられたクエリをテストできません。
-unicoletti

7

George MacKerronは、単純な最近傍関数を作成しましたが、これは非常に便利です。この関数は、指定されたフィーチャの最近傍のIDを返します。

create or replace function 
  nn(nearTo                   geometry
   , initialDistance          real
   , distanceMultiplier       real 
   , maxPower                 integer
   , nearThings               text
   , nearThingsIdField        text
   , nearThingsGeometryField  text)
 returns integer as $$
declare 
  sql     text;
  result  integer;
begin
  sql := ' select ' || quote_ident(nearThingsIdField) 
      || ' from '   || quote_ident(nearThings)
      || ' where st_dwithin($1, ' 
      ||   quote_ident(nearThingsGeometryField) || ', $2 * ($3 ^ $4))'
      || ' order by st_distance($1, ' || quote_ident(nearThingsGeometryField) || ')'
      || ' limit 1';
  for i in 0..maxPower loop
     execute sql into result using nearTo              -- $1
                                , initialDistance     -- $2
                                , distanceMultiplier  -- $3
                                , i;                  -- $4
    if result is not null then return result; end if;
  end loop;
  return null;
end
$$ language 'plpgsql' stable;

使用例:

SELECT id, nn(pt_geom,0.00001,2,100,'nw_node','node_id','node_geom') FROM my_point_table;

... my_point_tableのすべてのエントリに対してnw_nodeテーブルの最も近いノードを選択します。

ボストンGISサイトにはより一般的な機能もあります


私は、より一般的な意味でクエリ1:Nクエリを作成する方法に関心があります。たとえば、ジオメトリGに最も近い要素を見つける代わりに、Gと重複する最初の要素を見つけたい場合があります。情報にかかわらず、ありがとうございます。Boston GISへのリンクは非常に便利でした!私はすでにチートシートのいくつかを印刷しました:-)
Jmoney38

@ Jmoney48のように、質問をもう少し明確にするために言い換えることができます。最近傍の問題に特に興味があるのではなく、1つのジオメトリをテーブル内のすべてのジオメトリと比較する方法に興味がありますか?
暗闇

ボストンGISサイトの汎用機能を常に使用します。シンプルなものは、大きなテーブルに対しては非常に遅く、適用する労力はそれほど大きくありません。
Vladtn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.