テーブルからの行数に対してST_Intersection(clipper_geom, clipped_geom)
を実行したいと思います。
https://postgis.net/docs/ST_Intersection.html
https://postgis.net/docs/ST_Intersects.html
POSTGIS交差は、ST_Intersects()
とは異なり、ネイティブで複数のジオメトリの処理をサポートせず、ST_Intersects()
を使用して_clipper_geom
_と交差する行を選択する関数(テーブルを返す)を設計する必要がありました、結果セットをループし、ST_Intersection()
を使用して各交差を計算します。 geom
フィールドと_clipped_geom_wkt
_は、クリップされたジオメトリを記録するフィールドです。
関数は機能しますが、クリッピングを作成するテーブルごとに異なるものが必要です。入力テーブル(列名とタイプ)を動的に読み取り、RETURN
ステートメントで両方を定義したいと思います。
すべてのフィールド名とタイプは同じで、geom
のみが更新され、_clipped_geom_wkt
_が追加されます。
私はスタックオーバーフローを検索しようとしましたが、動的テーブル構造を作成する方法の例を見つけましたが、新しいデータを挿入/更新するために列名を一致させる必要がある最初の結果に対して後続のLOOP
を実行するものはありません。
これは私がこれまでに思いついたことですが、LOOP
部分を実行して_clipped_geom_wkt
_フィールドを追加し、geom
フィールドを更新する方法がわかりません。一部の応答では、SETOF
にフィールドが追加された場合、RETURNS TABLE (...)
を使用するように勧めています...
しかし、動的に生成された列は_RETURNS SETOF ...
_でのみサポートされているようです
_CREATE OR REPLACE FUNCTION clip_palin_polygon_complete(clipped_table text,clipper_geom text, age_sequence VARCHAR)
RETURNS TABLE (rec clipped_table, clipped_geom_wkt text)) AS $$ --not sure if this is the right way to do it...
DECLARE var_r record;
BEGIN
FOR var_r IN (
SELECT * FROM clipped_table
WHERE clipped_table.seq IN (age_sequence)
AND ST_Intersects(ST_GeomFromText(clipper_geom,4326), clipped_table.geom)
)
LOOP
/*
these are the original table fields that I would like to keep and match
dynamically with any table I have as input (clipped_table)
objectid := var_r.objectid;
seq := var_r.seq;
-- etc.
*/
--below there are the only two fields that need modifying
geom := (
SELECT ST_Intersection(ST_GeomFromText(clipper_geom, 4326), var_r.geom) AS geom);
clipped_geom_wkt := (
SELECT
ST_AsText(ST_Intersection(ST_GeomFromText(clipper_geom,4326), var_r.geom)) AS clipped_geom_wkt);
RETURN NEXT;
END LOOP;
END; $$
LANGUAGE 'plpgsql'
_
代わりに単純なSELECT
を使用して、すべての複雑化を回避できるはずです。
_SELECT t.*, ST_Intersection(x.geom, t.geom) AS geom2
FROM tbl t -- replace tbl with actual table
JOIN ST_GeomFromText($clipper_geom, 4326) AS x(geom) ON ST_Intersects(x.geom, t.geom)
WHERE t.seq = $age_sequence;
_
小さな違い:結果の元のgeom
と交差__geom2
_を取得します。本当に必要な場合は、冗長なST_AsText(ST_Intersection(x.geom, t.geom)) AS clipped_geom_wkt
をSELECT
リストに追加します。
次のような質問を理解しました。
さまざまな入力テーブルがあり、それぞれに_geom geometry
_列があります。関数がテーブル名と_clipper_geom geometry
_を入力として受け取り、_clipper_geom
_と交差するすべての行を返すようにしたい。 1列_clipped_geom_wkt text
_が追加され、geom
の値が変更されます。各列は_clipper_geom
_。との共通部分を示します
それは簡単なことではありません。 SQLは静的言語であり、関数は呼び出し時の戻り値の型を知る必要があります。ポリモーフィック型を使用すると動的な結果を得ることができますが、操作するには既知の行型が必要です。既存のテーブルの行タイプは適していますが、別の列を追加したいとします。それは簡単には不可能です。回避策は、多形の行タイプplusを追加の列で返すことです(すでに試したようです)。関数呼び出しの行タイプを分解して、目的の結果を取得します。
_CREATE OR REPLACE FUNCTION my_func(_tbl ANYELEMENT
, clipper_geom text
, age_sequence text)
RETURNS TABLE (tbl ANYELEMENT, clipped_geom_wkt text) AS
$func$
DECLARE
_geom geometry := ST_GeomFromText(clipper_geom, 4326); -- compute once
BEGIN
FOR tbl IN EXECUTE format(
'SELECT * FROM %s
WHERE seq = $1
AND ST_Intersects($2, geom)'
, pg_typeof(_tbl)
)
USING age_sequence -- data type must match!
, _geom
LOOP
tbl := tbl #= hstore('geom', ST_Intersection(_geom, tbl.geom));
clipped_geom_wkt := ST_AsText(tbl.geom);
RETURN NEXT;
END LOOP;
END
$func$ LANGUAGE plpgsql; -- don't quote the language name
_
電話(重要!):
_SELECT (tbl).*, clipped_geom_wkt
FROM my_func(NULL::public.clipped_table, $my_clipper_geom, $my_age_sequence);
_
Postgres 10で動作します。
注目すべき機能:
tbl
がRETURNS
句で暗黙的に定義され、入力タイプを動的にコピーする方法に注意してください(ANYELEMENT
)。したがって、推測したような多相型でSETOF
を使用する必要はありません。FOR-IN-EXECUTE
_ 動的クエリをループします。#=
_を使用した、まだ不明な列の割り当て。見る:(tbl).*
_を使用した関数呼び出しでの複合型の分解上記の設計にはこだわっていますが、この例では不要な複雑化です。追加の列_clipped_geom_wkt
_は完全に冗長です。関数呼び出しのgeom
からそれを派生させるだけです。次に、入力タイプを直接使用できます。
_CREATE OR REPLACE FUNCTION my_func2(_tbl ANYELEMENT
, clipper_geom text
, age_sequence text)
RETURNS SETOF ANYELEMENT AS
$func$
DECLARE
_geom geometry := ST_GeomFromText(clipper_geom, 4326);
BEGIN
FOR _tbl IN EXECUTE format(
'SELECT * FROM %s
WHERE seq = $1
AND ST_Intersects($2, geom)'
, pg_typeof(_tbl)
)
USING age_sequence -- data type must match!
, _geom
LOOP
_tbl := _tbl #= hstore('geom', ST_Intersection(_geom, _tbl.geom));
RETURN NEXT _tbl;
END LOOP;
END
$func$ LANGUAGE plpgsql;
_
コール:
_SELECT *, ST_AsText(geom) AS clipped_geom_wkt -- if you need the redundant column
FROM my_func2(NULL::public.clipped_table, $my_clipper_geom, $my_age_sequence);
_