2

我必须处理三个具有几何形状的表。

DECLARE
  CURSOR c1 IS
    SELECT
      store_number,
      0 AS total_area,
      0 AS bg_id,
      0 AS store_geom
    FROM table1 WHERE client_id = 1 AND org_id = 1;

  TYPE c1_tab_type IS TABLE OF c1%ROWTYPE;
  c1_list c1_tab_type;

BEGIN

  FOR r1 IN c1
  LOOP

    SELECT bg_id, store_number, total_area
    BULK COLLECT INTO c1_list
    FROM (
        SELECT
          bg_id,
          store_number,
          b.geometry                                                       store_geom,
          ((sdo_geom.SDO_AREA(sdo_geom.SDO_INTERSECTION(a.geometry, b.geometry, 0.005), 0.005, 'unit=sq_mile') /
            sdo_geom.SDO_AREA((a.geometry), 0.005, 'unit=sq_mile')) * 100) total_area
        FROM table2 a, table1 b
        WHERE store_number != r1.store_number
              AND sdo_relate(a.geometry, b.geometry, 'mask=anyinteract') = 'TRUE');

    IF total_area = 100 THEN
      FOR i IN 1..c1_list.count LOOP
        INSERT INTO temp_prop_area_100 VALUES c1_list(i);
      END LOOP;
    ELSE IF
      FOR i IN 1..c1_list.count LOOP
        INSERT INTO temp_Prop_area_block VALUES c1_list(i);
      END LOOP;
    END IF;

  END LOOP;
END;

因此,我从表 1 中选择了一条记录(所有三个表中最大的几何图形)并覆盖在表 2 中的较小多边形上。我从表 2 中获得了重叠几何图形的列表。这可能有一些相交和一些它们完全位于表 1 中的多边形之下。

然后我想把它们放到两个不同的表中。完全在 temp_prop_area 之下的和在 temp_prop_area_block 中相交的。

现在我遇到的问题是,当我获得所有相交多边形的 ID(temp_prop_area_block)时,我想将每个多边形覆盖在表 3 中的多边形上,哪些区域较小的多边形。同样找出它们相交的多边形以及什么是相交面积。

多边形大小依次是表 1 中的多边形最大,表 2 或 temp_prop_area_block 中的多边形,然后是表 3 中的多边形。

4

1 回答 1

2

你有几个选择。total_area在您定义的记录类型之外不存在,因此您不能在if显示的位置使用它,但您可以稍微调整一下:

...
                  For i in 1..c1_list.count loop
                       if c1_list(i).total_area=100
                          then                   
                            insert into temp_Prop_area_100
                            values c1_list(i);
                       else
                            insert into temp_Prop_area_block
                            values c1_list(i);
                       end if;
                  End Loop;
            End Loop;
End;

或者,您可以将列表分成两部分:

   Type C1_TAB_TYPE is table of c1%ROWTYPE;      
   c1_list c1_TAB_TYPE;
   c1_list_100 c1_TAB_TYPE;
   c1_list_block c1_TAB_TYPE;
...
                  For i in 1..c1_list.count loop
                       if c1_list(i).total_area=100
                          then                   
                            c1_list_100.extend();
                            c1_list_100(c1_list_100.last) := c1_list(i);
                       else
                            c1_list_block.extend();
                            c1_list_block(c1_list_block.last) := c1_list(i);
                       end if;
                  End Loop;

                  For i in 1..c1_list_100.count loop
                       insert into temp_Prop_area_100
                       values c1_list_100(i);
                  End Loop;
                  For i in 1..c1_list_block.count loop
                       insert into temp_Prop_area_block
                       values c1_list_block(i);
                  End Loop;
            End Loop;
End;

看起来它增加了额外的复杂性并没有太多收益,如果您继续使用单个插入,这可能是正确的。但这也允许您使用上一个答案forall中提到的语法:

    Type C1_TAB_TYPE is table of temp_prop_area%ROWTYPE;      
...
                  Forall i in 1..c1_list_100.count
                       insert into temp_Prop_area_100
                       values c1_list_100(i);
                  Forall i in 1..c1_list_block.count
                       insert into temp_Prop_area_block
                       values c1_list_block(i);
            End Loop;
End;

您也可以select ... bulk collect使用不同的过滤器在两个列表中执行单独的语句,但这涉及两次访问表并且可能效率较低。

于 2014-01-14T09:54:06.080 回答