This is the sort of thing that seems really easy in hindsight, but it took me a little while to get right.

There are lots of things that I don’t like about PL/SQL, but I often prefer to do spatial operations at the table level inside the database, rather than using ArcPy or ArcObjects; I think that it’s easier to reuse queries like this, the code tends to be more readable and concise, and performance is almost always significantly better.

In this case, we had a set of polygons (“PPAs”) that needed to be assigned a value based on the county they fell in, as well as being uniquely numbered within that county.

        select /*+ ordered use_nl (t,c) use_nl (t,p) */
        objectid,
        state,
        county_name county,
        region,
        row_number() over (partition by region, state, county_name
        order by region, state, county_name,
        sdo_geom.sdo_centroid(p.shape, 0.005).sdo_point.x,
        sdo_geom.sdo_centroid(p.shape, 0.005).sdo_point.y) as rnum
        from
        (
          select p.objectid, p.traps, c.state, c.county_name, p.region, sdo_geom.sdo_centroid(p.shape, 0.005) as shape
          from table(sdo_join('PPAS','SHAPE','COUNTIES','SHAPE')) t,
            ppas p,
            counties c
          where t.rowid1 = p.rowid
          and t.rowid2 = c.rowid
          and c.state = p.state
          and sdo_geom.relate(c.shape, 'anyinteract', sdo_geom.sdo_centroid(p.shape, 0.005), 0.005) = 'TRUE'
        ) p
        order by state, county_name, rnum

Ordering by the centroid X and Y values in the partition clause is important; without that, the polygons don’t get numbered in a deterministic way. In this case, the polygons were generated daily by a decision support system, and without ordering the blocks spatially, the numbers within each county would be swapped around each day.

comments powered by Disqus