PostgreSQL:如果下一个查询与上一个查询相交,则在下一个查询中排除几何体

PostgreSQL:如果下一个查询与上一个查询相交,则在下一个查询中排除几何体,postgresql,postgis,Postgresql,Postgis,我用这个查询来获取在另一个几何体中相交的几何体的数量: SELECT count(evidensapp_polystructures.brgy_locat) AS high, evidensapp_polystructures.brgy_locat AS barangay, evidensapp_polystructures.municipali AS municipality FROM evidensapp_floodhazard INNER JOIN evi

我用这个查询来获取在另一个几何体中相交的几何体的数量:

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;
正如您所注意到的,其
危险
等于
我还想得到与
危险
值相交的几何体的数量:
中等
。但是,如果某个几何体已经在
High
中相交,则在
Medium
查询中排除,同样的情况也发生在
Low
中,排除那些在
High
Medium中相交的几何体

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

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

预期结果应如下所示:

表格详情:

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中,您首先识别属于“高”危险类别的行,然后识别属于“中等”危险类别但
除外的行,然后识别属于“低”危险类别的行,除了列为“高”或“中等”的行。然后,在主查询中,将3个CTE与每个CTE的子查询中计算的每个barangay和市政计数合并。使用
完全连接
,这样,没有“高”危险等级结构的barangays和市政当局也会出现在结果中。

感谢这一点,我如何在一行中得出结果?如果是同一个barangay,则是同一行。您使用的是哪一版本的PG?它是9.3。基于预期输出,结果是正确的,但即使barangay相同,结果也不在一行中。顺便说一句,谢谢你的解释。请参阅更新的答案:使用联接而不是联合。在9.4中,您可以将
FILTER
子句与
count()
聚合一起使用,这就是我的问题。在提问时,你应该始终指出你的PG版本。好的..谢谢..我需要大约15分钟(874043毫秒)才能得到结果。但无论如何,我会研究更多如何优化它。你的回答将作为我的依据。