Как вставить точки из подзапроса как объект SDO_GEOMETRY в пространственную базу данных Oracle?

Скажем, у меня есть таблица с именем buildings который может быть создан с помощью следующего запроса:

create table buildings(
  building_id number primary key,
  building_name varchar2(32),
  shape sdo_geometry
);

Я могу вставить прямоугольник в него следующим запросом:

insert into buildings values(
  4, -- index
  'Reading Room', -- building_name
  sdo_geometry(
    2003, --SDO_GTYPE: dltt - 2(2D)0(linear referencing)03(polygon)
    8307, --SDO_SRID: coordinate system
    null, --SDO_POINT: it is for point inserting, if the next two field = null, then it could not be null.
    sdo_elem_info_array( --SDO_ELEM_INFO:
    1, --SDO_STARTING_OFFSET: indicates from which index of the next param of SDO_GEOMETRY would be considered, starts from 1.
    1003, --SDO_ETYPE: 1(exterior, interior  - 2)003(this digits usually comes from SDO_GTYPE)
    3),  --SDO_INTERPRETATION: 1 - simple polygon, 2 - polygon connecting arcs, 3 - rectangle, 4 - circle etc.
    sdo_ordinate_array(
      24.916312, 91.832393,
      24.916392, 91.832678
    ) --SDO_ORDINATES: co-ordinates of the geometry
                              -- two corner points of the main diagonal
  )
);

Здесь две геодезические точки пришли из реальных данных как объект sdo_ordinate_array, Следующие две точки вставляются непосредственно в вышеупомянутый запрос:

  1. 24,916312, 91,832393
  2. 24,916392, 91,832678

Теперь я хочу вставить эти две точки из двух разных подзапросов.

Подзапросы будут выглядеть следующим образом:

SELECT 180+SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.X, 
  180-SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.Y
  FROM buildings c, user_sdo_geom_metadata m 
  WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
  AND c.building_name = 'IICT';

Итак, результат запроса будет выглядеть так:

         X          Y
---------- ----------
24.9181097 91.83097409 

Как я могу преобразовать этот результат в значение, разделенное запятыми, например: 24.9181097, 91.83097409?

Чтобы я мог заменить следующий код:

sdo_ordinate_array(
    24.916312, 91.832393,
    24.916392, 91.832678
) --SDO_ORDINATES: co-ordinates of the geometry

с:

sdo_ordinate_array(
    (/*sub-query*/),
    (/*another-subquery*/)
) --SDO_ORDINATES: co-ordinates of the geometry

Я прогуглил это и исследовал несколько блогов, но безуспешно.

NB:

Название казалось неуместным, но прямые версии подзапросов возвращают объект SDO_GEOMETRY, Если вы изучали пространственные запросы оракула, то вам ясно, что я просто извлекаю значения X и Y из возвращенного объекта.

2 ответа

Решение

Я нашел способ вставить. Может существовать эффективный способ, но этот работает нормально.

sdo_ordinate_array(

    --this sub-query returns the Longitude of the first point
    (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.X X
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT'), 

    --this sub-query returns the Latitude of the first point
    (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.Y Y
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT'), 

    --this sub-query returns the Longitude of the second point
    (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.X X 
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT'), 

    --this sub-query returns the Latitude of the second point
    (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.Y Y 
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT') 

) --SDO_ORDINATES: co-ordinates of the geomentry

sdo_ordinate_array берет только очки, а не объект sdo_geometry, Итак, я должен получить долготу и широту отдельно.

Итак, полный запрос вставки будет выглядеть следующим образом:

insert into buildings values(
  4, -- index
  'Reading Room', -- building_name
   sdo_geometry(
    2003, --SDO_GTYPE: dltt - 2(2D)0(linear referencing)03(polygon)
    8307, --SDO_SRID: coordinate system
    null, --SDO_POINT: it is for point inserting, if the next two field = null, then it could not be null.
    sdo_elem_info_array( --SDO_ELEM_INFO:
    1, --SDO_STARTING_OFFSET: indicates from which index of the next param of SDO_GEOMETRY would be considered, starts from 1.
    1003, --SDO_ETYPE: 1(exterior, interior  - 2)003(this digits usually comes from SDO_GTYPE)
    3),  --SDO_INTERPRETATION: 1 - simple polygon, 2 - polygon connecting arcs, 3 - rectangle, 4 - circle etc.

    sdo_ordinate_array(

        --this sub-query returns the Longitude of the first point
        (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.X X
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT'), 

        --this sub-query returns the Latitude of the first point
        (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.Y Y
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT'), 

        --this sub-query returns the Longitude of the second point
        (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.X X 
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT'), 

        --this sub-query returns the Latitude of the second point
        (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.Y Y 
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT') 

    ) --SDO_ORDINATES: co-ordinates of the geomentry
 )
);

Функция SDO_CENTROID() возвращает объект SDO_GEOMETRY, который затем можно использовать для вставки в таблицу результатов.

Предполагая, что это ваша таблица результатов

create table building_centroids (
  building_id number primary key,
  centroid sdo_geometry
);

Тогда следующее заполнит его центроидами всех ваших зданий

insert into building_centroids (building_id, centroid)
select building_id, sdo_geom.sdo_centroid(shape, 0.05)
from buildings;

Я не понимаю, зачем вам нужно менять координаты (180+ х, 180-й). Это бессмысленно.

Во всяком случае, вы говорите, что выше не то, что вы хотите. Я продолжу гадать и предположить, что вы хотите построить прямоугольник, в котором два угла вычисляются как центроиды в двух ваших зданиях. Для этого нужно немного PL/SQL, например:

Сначала определите функцию, которая строит прямоугольник из двух входных точек

create or replace function rectangle_from_points (
  point_1 sdo_geometry,
  point_2 sdo_geometry
) 
return sdo_geometry
as 
  rectangle sdo_geometry;
begin
  -- Initialize resulting rectangle
  rectangle := sdo_geometry (2003, point_1.sdo_srid, null,
     sdo_elem_info_array (1,1003,3),
     sdo_ordinate_array()
  );
  -- Fill it with the two point points
  rectangle.sdo_ordinates.extend(4);
  rectangle.sdo_ordinates(1) := point_1.sdo_point.x;
  rectangle.sdo_ordinates(2) := point_1.sdo_point.y;
  rectangle.sdo_ordinates(3) := point_2.sdo_point.x;
  rectangle.sdo_ordinates(4) := point_2.sdo_point.y;
  -- Return it
  return rectangle;
end;
/

Теперь используйте это так:

select rectangle_from_points (
  (
    select sdo_geom.sdo_centroid(shape, 0.05)
    from buildings
    building_id = 42
  ),
  (
    select sdo_geom.sdo_centroid(shape, 0.05)
    from buildings
    building_id = 564
  )
)
from dual;

Если это не то, что вы ожидаете, то, пожалуйста, перефразируйте вопрос (а также уточните реальную бизнес-проблему, которую вы пытаетесь решить)

Другие вопросы по тегам