PostgreSQL:如果下一个查询与前一个查询相交,则排除下一个查询的几何图形

PostgreSQL: Exclude geometries on the next query if it intersects on the previous one

我有这个查询来获取与另一个几何相交的几何数:

SELECT  count(evidensapp_polystructures.brgy_locat) AS high,
        evidensapp_polystructures.brgy_locat AS barangay,
        evidensapp_polystructures.municipali AS municipality
FROM evidensapp_floodhazard
INNER JOIN evidensapp_polystructures
      ON st_intersects(evidensapp_floodhazard.geom, evidensapp_polystructures.geom) 
      AND evidensapp_floodhazard.hazard= 'High'
GROUP BY evidensapp_polystructures.brgy_locat, evidensapp_polystructures.municipali;

如您所见,它的 hazard 等于 High我还想获得与 hazard 值相交的几何数:MediumLow。但是,如果某个几何图形已经在 High 中相交,则在其中排除 Medium 查询并且 Low 也排除那些在 HighMedium 中相交的几何图形.

我有这个想法,也许使用 CASE 或者我需要获取几何体的 id 然后在查询中尝试 NOT IN 但不知道如何去做。可能是因为我是 PostgreSQL 或任何数据库工作的新手。

下面是上述查询的示例结果:

预期的结果应该是这样的:

Table 详情:

CREATE TABLE evidensapp_floodhazard (
  id serial NOT NULL,
  hazard character varying(6) NOT NULL,
  date_field character varying(60),
  geom geometry(MultiPolygon,32651),
  CONSTRAINT evidensapp_floodhazard_pkey PRIMARY KEY (id)
);

CREATE INDEX evidensapp_floodhazard_geom_id
  ON evidensapp_floodhazard USING gist (geom);

ALTER TABLE evidensapp_floodhazard CLUSTER ON evidensapp_floodhazard_geom_id;

CREATE TABLE evidensapp_polystructures (
  id serial NOT NULL,
  bldg_name character varying(100) NOT NULL,
  bldg_type character varying(50) NOT NULL,
  brgy_locat character varying(50) NOT NULL,
  municipali character varying(50) NOT NULL,
  province character varying(50) NOT NULL,
  geom geometry(MultiPolygon,32651),
  CONSTRAINT evidensapp_polystructures_pkey PRIMARY KEY (id)
);

CREATE INDEX evidensapp_polystructures_geom_id
  ON evidensapp_polystructures USING gist (geom);

ALTER TABLE evidensapp_polystructures CLUSTER ON evidensapp_polystructures_geom_id;

由于字符串"High"、"Medium"和"Low"在比较方面几乎无能为力,因此必须使用子查询。具有一些 CTE 的解决方案可能是最干净的:

WITH hi AS (
  SELECT ps.id, ps.brgy_locat, ps.municipali
  FROM evidensapp_polystructures ps
  JOIN evidensapp_floodhazard fh ON fh.hazard = 'High'
                                 AND ST_Intersects(fh.geom, ps.geom)
), med AS (
  SELECT ps.id, ps.brgy_locat, ps.municipali
  FROM evidensapp_polystructures ps
  JOIN evidensapp_floodhazard fh ON fh.hazard = 'Medium'
                                 AND ST_Intersects(fh.geom, ps.geom)
  EXCEPT SELECT * FROM hi
), low AS (
  SELECT ps.id, ps.brgy_locat, ps.municipali
  FROM evidensapp_polystructures ps
  JOIN evidensapp_floodhazard fh ON fh.hazard = 'Low'
                                 AND ST_Intersects(fh.geom, ps.geom)
  EXCEPT SELECT * FROM hi
  EXCEPT SELECT * FROM med
)
SELECT brgy_locat AS barangay, municipali AS municipality, high, medium, low
FROM (SELECT brgy_locat, municipali, count(*) AS high
      FROM hi
      GROUP BY 1, 2) cnt_hi
FULL JOIN (SELECT brgy_locat, municipali, count(*) AS medium
      FROM med
      GROUP BY 1, 2) cnt_med USING (brgy_locat, municipali)
FULL JOIN (SELECT brgy_locat, municipali, count(*) AS low
      FROM low
      GROUP BY 1, 2) cnt_low USING (brgy_locat, municipali);

在三个 CTE 中,您首先确定属于 "high" 危险类别的行,然后是 "medium" 危险类别中的行,但 EXCEPT 已经属于 "high" 类别,然后是 "low" 危险类别中的那些,但列为 "high" 或 "medium" 的除外。然后,在主查询中,您将 3 个 CTE 与每个 CTE 的子查询中计算的每个 barangay 和自治市的计数结合起来。 FULL JOIN 的使用使得在 "high" 危害 class 中没有建筑物的村镇和市政当局也会出现在结果中。