この種の問題に対する最も効率的なアプローチは、SDO_JOIN() フィルターを使用することです。空間インデックスを使用して、多くのオブジェクトを他の多くのオブジェクトと空間的に効率的に照合するように設計されています。
テーブルが次のようになっていると想定しています。
create table ottawacollectors (
road_id number,
segment_id number,
road_name varchar2(30),
geometry sdo_geometry,
primary key (road_id, segment_id)
);
道路セグメントが含まれています。各道路セグメントは、道路識別子とセグメント識別子によって識別されます。
次の例では、2 つの道路セグメントが交差するたびに、交差点ごとに 1 行を含む新しいテーブル INTERSECTIONS を作成します。交点は幾何学的点として計算されます。各行には、各セグメントの識別子 (道路識別子とセグメント識別子) と各道路の名前が含まれています。
create table intersections as
select a.road_id road_id_1, a.segment_id segment_id_1, a.road_name road_name_1,
b.road_id road_id_2, b.segment_id segment_id_2, b.road_name road_name_2,
sdo_geom.sdo_intersection (
a.geometry, b.geometry, 0.05
) intersection_point
from ottawacollectors a,
ottawacollectors b,
table (
sdo_join(
'OTTAWACOLLECTORS','GEOMETRY',
'OTTAWACOLLECTORS','GEOMETRY',
'MASK=ANYINTERACT'
)
) j
where a.rowid = j.rowid1
and b.rowid = j.rowid2
and j.rowid1 > j.rowid2;
いくつかの説明:
SDO_JOIN()
「テーブル」関数です。2 つの入力テーブルの名前 (テーブル名とジオメトリ列の名前) と一致基準 (ここでは "ANYINTERACT") を取ります。これは、あらゆる種類の相互作用を意味します。
- 要素の VARRAY を返します。各要素には、相互に作用する道路セグメントのカップルを指す ROWID1 および ROWID2 と呼ばれる ROWID (テーブル内の行の物理識別子) のペアが含まれます。
- コンストラクターは、その
TABLE()
配列をキャストして通常のテーブルのように見せ、リレーショナル クエリに簡単に埋め込むことができます。その「仮想」テーブルは、クエリでは J と呼ばれます。
- また、クエリは
OTTAWACOLLECTORS
テーブルを 2 回読み取ります (例のように)。TABLE()
それらを結果と結合します。J.ROWID1=A.ROWID AND J.ROWID2=B.ROWID
- フィルターは、
J.ROWID1>J.ROWID2
不要な結果を排除するためにあります。道路セグメント A と B が交差しているとします。SDO_JOIN は、(A,B) だけでなく、(B,A) と (A,A) と (B,B) の 4 つの組み合わせを返します。行 ID を比較する目的は、(A,B) または (B,A) のいずれかのみを保持することです。
- 選択リストには、2 つのセグメントの完全な識別子、名前、および交点 (
SDO_GEOM.SDO_INTERSECTION()
例のように計算されたもの) が含まれます。
- 最後に、結果がテーブルに書き込まれます
このクエリはすぐに結果を返さないことに注意してください。処理する必要がある道路セグメントの数や、もちろんクエリを実行するハードウェアによっては、完了するまでに数分かかる場合があります。Oracle 12c (12.1.0.1 または 12.1.0.2) で実行し、Oracle Spatial の適切なライセンスを所有している場合は、Vector Performance Accelerator オプションがオンになっていることを確認してください。