根据 x 和 y 坐标列表从 Oracle 查询几何对象列表

Querying a list of geometry objects from Oracle based on list of x and y coordinates

我们正在使用具有 SDO_GEOMETRY 个对象的 Oracle 数据库 table。我想 return 具有几何对象的列包含某个 point (x,y 坐标)的行。

我知道我可以使用这样的单点几何查询 table:

[..]
WHERE SDO_CONTAINS(D.D_SHAPE, SDO_GEOMETRY(
      2001,
      NULL,
      SDO_POINT_TYPE(<myXCoordinate>, <myYCoordinate>, NULL),
      NULL,
      NULL)) = 'TRUE'

但是假设我有一个 list 坐标,并且我想要所有几何体 objects/rows,其中对象至少包含列表中的一个坐标。我该怎么做?

我知道我可以例如实现一个 OR 并做类似的事情:

WHERE SDO_CONTAINS(D.D_SHAPE, SDO_GEOMETRY(
        2001,
        NULL,
        SDO_POINT_TYPE(<myXCoordinate1>, <myYCoordinate1>, NULL),
        NULL,
        NULL)) = 'TRUE'
   OR SDO_CONTAINS(D.D_SHAPE, SDO_GEOMETRY(
        2001,
        NULL,
        SDO_POINT_TYPE(<myXCoordinate2>, <myYCoordinate2>, NULL),
        NULL,
        NULL)) = 'TRUE'

但是当有一个列表时,这似乎不能很好地扩展。 1000个坐标对吧?

另外,我可能有一个带有 x 和 y 坐标的临时 table,并且想使用连接。不确定在这里该怎么做?

您可以使用 SDO_CONTAINS 函数将您的点“列表”与 table 形状连接起来。

如果此列表来自其他 table,您可以按原样应用连接(或通过构建 SDO_GEOMETRY 类型的点)。如果您需要“手动”传递它们,那么没有选择,因为我不知道 Oracle 中方便的行集生成函数(如其他 DBMS 中的 select ... from values ...)。一些练习可以用 JSON 来完成,或者你可以使用集合类型作为记录的来源,它可以手动“输入”或从外部传递。

insert into poly
/*Growing squares centered in (0,0)*/
select 
  level
  , sdo_geometry(
    2003
    , null, null
    , SDO_ELEM_INFO_ARRAY(1, 1003, 3)
    , SDO_ORDINATE_ARRAY(-level, -level, level, level)
  )
from dual
connect by level < 6
insert into point
/*List of points (0, y)*/
select
  level
  , 0
  , level
from dual
connect by level < 8
select
  p.*
  , pl.id as contained_in
  , pl.poly.get_wkt() as contained_in_wkt
from point p
  left join poly pl
    /*You may construct point on-the-fly from its coordinates*/
    on SDO_CONTAINS(pl.poly, sdo_geometry(
      2001
      , null
      , sdo_point_type(p.x, p.y, null)
      , null
      , null
    )) = 'TRUE'
where 1 = 1
order by
  p.id
  , pl.id
ID |  X |  Y | CONTAINED_IN | CONTAINED_IN_WKT                                             
-: | -: | -: | -----------: | :------------------------------------------------------------
 1 |  0 |  1 |            2 | POLYGON ((-2.0 -2.0, 2.0 -2.0, 2.0 2.0, -2.0 2.0, -2.0 -2.0))
 1 |  0 |  1 |            3 | POLYGON ((-3.0 -3.0, 3.0 -3.0, 3.0 3.0, -3.0 3.0, -3.0 -3.0))
 1 |  0 |  1 |            4 | POLYGON ((-4.0 -4.0, 4.0 -4.0, 4.0 4.0, -4.0 4.0, -4.0 -4.0))
 1 |  0 |  1 |            5 | POLYGON ((-5.0 -5.0, 5.0 -5.0, 5.0 5.0, -5.0 5.0, -5.0 -5.0))
 2 |  0 |  2 |            3 | POLYGON ((-3.0 -3.0, 3.0 -3.0, 3.0 3.0, -3.0 3.0, -3.0 -3.0))
 2 |  0 |  2 |            4 | POLYGON ((-4.0 -4.0, 4.0 -4.0, 4.0 4.0, -4.0 4.0, -4.0 -4.0))
 2 |  0 |  2 |            5 | POLYGON ((-5.0 -5.0, 5.0 -5.0, 5.0 5.0, -5.0 5.0, -5.0 -5.0))
 3 |  0 |  3 |            4 | POLYGON ((-4.0 -4.0, 4.0 -4.0, 4.0 4.0, -4.0 4.0, -4.0 -4.0))
 3 |  0 |  3 |            5 | POLYGON ((-5.0 -5.0, 5.0 -5.0, 5.0 5.0, -5.0 5.0, -5.0 -5.0))
 4 |  0 |  4 |            5 | POLYGON ((-5.0 -5.0, 5.0 -5.0, 5.0 5.0, -5.0 5.0, -5.0 -5.0))
 5 |  0 |  5 |         null | null                                                         
 6 |  0 |  6 |         null | null                                                         
 7 |  0 |  7 |         null | null                                                         

下面是集合类型示例。

/*Object type to access instances as a single field*/
create type ts_sdo as object (
  shape sdo_geometry
)
/*Table of SDO_GEOMETRY*/
create type tt_sdo as varray (1048576) of ts_sdo
select
  p.shape.get_wkt() as point_wkt
  , pl.id as contained_in
  , pl.poly.get_wkt() as contained_in_wkt
from table(
  /*Then we construct collection from list of points*/
  tt_sdo(
    /*Each member is constructed from SDO_GEOMETRY*/
    ts_sdo(sdo_geometry('POINT(0 1)'))
    , ts_sdo(sdo_geometry(
      2001
      , null
      , sdo_point_type(0, 10, 0)
      , null
      , null
    ))
  )) p
  left join poly pl
    on SDO_CONTAINS(pl.poly, p.shape) = 'TRUE'
where 1 = 1
order by
  pl.id
POINT_WKT        | CONTAINED_IN | CONTAINED_IN_WKT                                             
:--------------- | -----------: | :------------------------------------------------------------
POINT (0.0 1.0)  |            2 | POLYGON ((-2.0 -2.0, 2.0 -2.0, 2.0 2.0, -2.0 2.0, -2.0 -2.0))
POINT (0.0 1.0)  |            3 | POLYGON ((-3.0 -3.0, 3.0 -3.0, 3.0 3.0, -3.0 3.0, -3.0 -3.0))
POINT (0.0 1.0)  |            4 | POLYGON ((-4.0 -4.0, 4.0 -4.0, 4.0 4.0, -4.0 4.0, -4.0 -4.0))
POINT (0.0 1.0)  |            5 | POLYGON ((-5.0 -5.0, 5.0 -5.0, 5.0 5.0, -5.0 5.0, -5.0 -5.0))
POINT (0.0 10.0) |         null | null                                                         

db<>fiddle here