简体   繁体   中英

Finding neighbouring polygons - postgis query

The problem: I have a table full of polygons (districts of a country). Some of these polygons have a certain attribute that may or may not be checked. In this case the attribute is called "spread" and the "checked" value is 1.

Now I'd like to run a query that finds all the "checked" polygons. Something like:

SELECT * FROM gemstat WHERE spread = 1

and then I'd like to set the "spread" attribute to "1" in every neighbouring polygon that isn't already checked. (I also want to set a second attribute, but that's just a minor addition)

First, let's start with a query that selects all polygons that are neighbours of a polygon with a spread-value = 1

SELECT (b."GEM_NR")
FROM gemstat_simple5 as a
JOIN gemstat_simple5 as b
ON ST_Touches((a.the_geom),b.the_geom)
where a.spread =1;

This query returns all polygons that are neighbours of a polygon with spread = 1

Now I want to update the table based on the results of that subquery. This is realized with this piece of code provided by John Powell aka Barca (see answer and also comments below):

Update gemstat_simple5 gem set spread=1, time=2
FROM (
   SELECT (b."GEM_NR")
   FROM gemstat_simple5 as a,
   gemstat_simple5 as b
   WHERE ST_Touches(a.the_geom, b.the_geom) 
   AND a."GEM_NR" != b."GEM_NR"
   AND a.spread = 1
) as subquery
WHERE gem."GEM_NR" = subquery."GEM_NR"

Run this query and it will set the attributes spread to 1 and time to 2 of the adjacent polygons while not touching the original polygons with spread = 1. Therefore it poses the perfect answer to my question.

If you are asking how to update a table based on a subquery finding only those polygons that have a neighbor (ie, they touch another polygon), then the following should work for you.

Update gemstat_simple5 gem set spread=1, time=2
  FROM (
     SELECT (b."GEM_NR")
       FROM gemstat_simple5 as a,
            gemstat_simple5 as b
       WHERE ST_Touches(a.the_geom, b.the_geom) 
       AND a."GEM_NR" != b."GEM_NR"
       AND a.spread = 1
     ) as subquery
 WHERE gem."GEM_NR" = subquery."GEM_NR"

Note, I have put AND a."GEM_NR" < b."GEM_NR", which both avoids the case where AND a."GEM_NR" = b."GEM_NR", ie, itself, which you want to avoid, and also reduces the pair wise comparisons by half. I have also use the a, b Where approach rather then a join b on st_touches, which is the same, but I find more confusing with spatial joins. Finally, you just equate the table GEM_NR you are updating with those found in the sub query.

The direct answer is

SELECT a.*
FROM polygon1 as a
JOIN polygon1 as b
ON st_intersects((st_buffer(a.the_geom,0.00001)),b.the_geom) 
where b.id = 561334;

Tested in my Machine and it also gives the id which you give in where class. My polygon table's Spatial Reference - EPSG:4326...

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM