データの座標系は何ですか? そして、最も重要なことは、メタデータにどの程度の許容範囲を設定したか?
その他のコメント:
1) リレート バッファ アプローチを使用しないでください。距離内アプローチを使用してください。
2) そのようなクエリには PL/SQL ループは必要ありません。単純な CTAS を使用するだけです。
create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c2.mi_prinx <> c1.mi_prinx;
3) 書かれているように、2 cm 以内にあるポイント A と B のペアは 2 回返されます: 1 回は (A,B) として、もう 1 回は (B,A) として返されます。それを回避する (そしていずれかのケースのみを返す) には、次のようにクエリを記述します。
create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c1.rowid < c2.rowid;
3) あなたが言及したポイント数 (400000+) の処理は、次のように SDO_JOIN 手法を使用してより適切に実行する必要があります。
create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from table (
sdo_join (
'ORAHAN','GEOLOC',
'ORAHAN','GEOLOC',
'DISTANCE=2 UNIT=CM'
)
) j,
orahan c1,
orahan c2
where j.rowid1 < j.rowid2
and c1.rowid = j.rowid1
and c2.rowid = j.rowid2;
データベース サーバーの容量によっては、処理に時間がかかる場合があります。Oracle Enterprise Edition のライセンスがあり、ハードウェアに適切な容量 (コア数) がある場合、並列処理によって経過時間を短縮できます。
4) Oracle 11g を使用しているとのことです。正確なバージョンは? バージョン 11.2.0.4 は、11gR2 のターミナル リリースです。それより古いものはサポートされなくなりました。これで、実際には 12cR1 (12.1.0.2) になっているはずです。あなたの場合の 12.1.0.2 の主な利点は、多くの空間関数と演算子を高速化する Vector Performance Accelerator 機能です (適切な Oracle Spatial ライセンスを所有している場合のみ - 無料の Oracle Locator 機能では利用できません)。
======================================
あなたの例で2つのポイントを使用してください。距離を計算しましょう:
select sdo_geom.sdo_distance(
sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),
sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
0.005
) distance
from dual;
DISTANCE
----------
.01000197
1 row selected.
SRID を指定していないことに注意してください。座標がメートルで表されていると仮定すると、それらの間の距離は実際には 1 cm 強です。
======================================
お気づきのように、元の構文が機能しない理由は、SDO_BUFFER() 呼び出しに指定した許容誤差のためです。0.5 (=50cm) として渡すと、半径 0.02 (2cm) のバッファーが生成されます。その効果は、生成されたバッファーがポイント自体に効果的に溶解することです。
たとえば、公差 0.5 の場合:
select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.5) from dual;
プロデュース:
SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(521554.782, 4230983.08, NULL), NULL, NULL)
公差 0.005:
select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005) from dual;
適切なバッファーを取得します。
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 2), SDO_ORDINATE_ARRAY(521554.782, 4230983.06, 521554.802, 4230983.08, 521554.782, 4230983.1, 521554.762, 4230983.08, 521554.782, 4230983.06))
そして、非常に近い点がそのバッファと一致するようになりました:
select sdo_geom.relate(
sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005),
'determine',
sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
0.005
) relation
from dual;
RELATION
-------------------------
CONTAINS
1 row selected.
======================================
データに適切な明示的な SRID がないという事実は、測定または距離ベースの検索で明示的な単位を使用できないことを意味します。データベースはデータがどの座標系にあるかを認識していないため、2 つの点が設定された cm または m の間隔よりも小さいかどうかを判断する方法がわかりません。できることは、座標がメートル単位であると想定することだけです。
したがって、上記の例では、次のように置き換え'DISTANCE=2 UNIT=CM'
ます'DISTANCE=0.02'