WITH hi AS (
SELECT ps.id, ps.brgy_locat, ps.municipali, ps.bldg_name, fh.gridcode, ps.bldg_type
FROM evidensapp_polystructures ps
JOIN evidensapp_floodhazard fh ON fh.gridcode=3
AND ST_Intersects(fh.geom, ps.geom)
), med AS (
SELECT ps.id, ps.brgy_locat, ps.municipali ,ps.bldg_name, fh.gridcode, ps.bldg_type
FROM evidensapp_polystructures ps
JOIN evidensapp_floodhazard fh ON fh.gridcode=2
AND ST_Intersects(fh.geom, ps.geom)
EXCEPT SELECT * FROM hi
), low AS (
SELECT ps.id, ps.brgy_locat, ps.municipali,ps.bldg_name, fh.gridcode, ps.bldg_type
FROM evidensapp_polystructures ps
JOIN evidensapp_floodhazard fh ON fh.gridcode=1
AND ST_Intersects(fh.geom, ps.geom)
EXCEPT SELECT * FROM hi
EXCEPT SELECT * FROM med
)
SELECT brgy_locat, municipali, bldg_name, bldg_type, gridcode, count( bldg_name)
FROM (SELECT brgy_locat, municipali, bldg_name, gridcode, bldg_type
FROM hi
GROUP BY 1, 2, 3, 4, 5) cnt_hi
FULL JOIN (SELECT brgy_locat, municipali,bldg_name, gridcode, bldg_type
FROM med
GROUP BY 1, 2, 3, 4, 5) cnt_med USING (brgy_locat, municipali, bldg_name,gridcode,bldg_type)
FULL JOIN (SELECT brgy_locat, municipali,bldg_name,gridcode, bldg_type
FROM low
GROUP BY 1, 2, 3, 4, 5) cnt_low USING (brgy_locat, municipali, bldg_name, gridcode, bldg_type)
上面的查询返回错误:
错误:列" cnt_hi.brgy_locat"必须出现在GROUP BY子句中 或用于聚合函数 **********错误**********
错误:列" cnt_hi.brgy_locat"必须出现在GROUP BY子句中 或者在聚合函数SQL状态中使用:42803
但是,如果我省略count(bldg_name)
它的工作原理。但我需要根据bldg_name
计算。
修改 我想获得与危险值(gridcode)相交的建筑物数量:High(3),Medium(2)和Low(1)。但是,如果某个几何体已经在“高”中相交,则在其中排除“中”查询,同样与“低”相同,排除那些在“高”和“中”中相交的几何体。
PostgreSQL:9.4,PostGIS:2.1.7
表格详情:
CREATE TABLE evidensapp_floodhazard (
id integer NOT NULL DEFAULT nextval('evidensapp_floodhazard_id_seq'::regclass),
gridcode integer 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;
编辑2: 尽管我尽力解释预期的输出是什么,但无论如何:
bldg_name
而不是id
,其中floodhazard
中的网格代码与 EDIT 1 上面提到的条件相交。brgy_locat
,brgy_municipali
以及它所属的gridcode
和bldg_type
。请看一下上面的图片。
答案 0 :(得分:2)
你可能想要这个:
WITH hi AS (
SELECT ps.brgy_locat, ps.municipali, ps.bldg_name, ps.bldg_type, fh.gridcode
, count(*) OVER(PARTITION BY ps.bldg_name, ps.bldg_type) AS building_count
FROM evidensapp_polystructures ps
JOIN evidensapp_floodhazard fh ON fh.gridcode = 3
AND ST_Intersects(fh.geom, ps.geom)
)
, med AS (
SELECT ps.brgy_locat, ps.municipali, ps.bldg_name, ps.bldg_type, fh.gridcode
, count(*) OVER(PARTITION BY ps.bldg_name, ps.bldg_type) AS building_count
FROM evidensapp_polystructures ps
JOIN evidensapp_floodhazard fh ON fh.gridcode = 2
AND ST_Intersects(fh.geom, ps.geom)
LEFT JOIN hi USING (bldg_name, bldg_type)
WHERE hi.bldg_name IS NULL
)
TABLE hi
UNION ALL
TABLE med
UNION ALL
SELECT ps.brgy_locat, ps.municipali, ps.bldg_name, ps.bldg_type, fh.gridcode
, count(*) OVER(PARTITION BY ps.bldg_name, ps.bldg_type) AS building_count
FROM evidensapp_polystructures ps
JOIN evidensapp_floodhazard fh ON fh.gridcode = 1
AND ST_Intersects(fh.geom, ps.geom)
LEFT JOIN hi USING (bldg_name, bldg_type)
LEFT JOIN med USING (bldg_name, bldg_type)
WHERE hi.bldg_name IS NULL
AND med.bldg_name IS NULL;
根据您对问题和聊天的评论,现在按 (bldg_name, bldg_type)
计算 - 排除已在较高级别相交的建筑物 - 再次基于(bldg_name, bldg_type)
。
所有其他列与计数(id
,geom
,...)不同(brgy_locat
,municipali
)或功能相关的噪音。 如果不是,请在PARTITION BY
子句中添加更多列以消除建筑物的歧义。并将相同的列添加到JOIN条件的USING子句中。
如果某个建筑物与evidensapp_floodhazard
中的多个行相交且 相同 gridcode
,那么它会被计算多次。见另一击。
由于您实际上并不想聚合行而只是依靠分区,因此关键功能是将count()
用作window function,而不是像原始版本那样使用聚合函数。基本解释:
count(*)
在这方面做得更好:
使用LEFT JOIN
/ IS NULL
代替EXCEPT
。详细说明:
我没有在外部查询中看到FULL JOIN
的目的。改为使用UNION ALL
。
这会计算构建 一次 ,无论它在同一网格代码级别与evidensapp_floodhazard
相交多少次
此外,此变体(与第一个不同!)假定同一(bldg_name, bldg_type)
的所有行在同一网格代码级别上匹配,这可能是也可能不是这样:
SELECT brgy_locat, municipali, bldg_name, bldg_type, 3 AS gridcode
, count(*) OVER(PARTITION BY bldg_name, bldg_type) AS building_count
FROM evidensapp_polystructures ps
WHERE EXISTS (
SELECT 1 FROM evidensapp_floodhazard fh
WHERE fh.gridcode = 3 AND ST_Intersects(fh.geom, ps.geom)
)
UNION ALL
SELECT brgy_locat, municipali, bldg_name, bldg_type, 2 AS gridcode
, count(*) OVER(PARTITION BY bldg_name, bldg_type) AS building_count
FROM evidensapp_polystructures ps
WHERE EXISTS (
SELECT 1 FROM evidensapp_floodhazard fh
WHERE fh.gridcode = 2 AND ST_Intersects(fh.geom, ps.geom)
)
AND NOT EXISTS (
SELECT 1 FROM evidensapp_floodhazard fh
WHERE fh.gridcode > 2 -- exclude matches on **all** higher gridcodes
AND ST_Intersects(fh.geom, ps.geom)
)
UNION ALL
SELECT brgy_locat, municipali, bldg_name, bldg_type, 1 AS gridcode
, count(*) OVER(PARTITION BY bldg_name, bldg_type) AS building_count
FROM evidensapp_polystructures ps
WHERE EXISTS (
SELECT 1 FROM evidensapp_floodhazard fh
WHERE fh.gridcode = 1 AND ST_Intersects(fh.geom, ps.geom)
)
AND NOT EXISTS (
SELECT 1 FROM evidensapp_floodhazard fh
WHERE fh.gridcode > 1 AND ST_Intersects(fh.geom, ps.geom)
);
还演示了没有CTE的变体,根据数据分布,这些变体可能会或可能不会表现得更好。
将gridcode
添加到索引可能会提高性能。 (未使用PostGis进行测试):
您需要首先安装附加模块btree_gist
。详细说明:
CREATE INDEX evidensapp_floodhazard_geom_id
ON evidensapp_floodhazard USING gist (gridcode, geom);
答案 1 :(得分:1)
错误是要求您在<Directory /path/to/home*>
Order deny,allow
Deny from all
</Directory>
<Directory /path/to/home/subdirectory-for-dev*>
Order deny,allow
Deny from all
allow from 111.222.333.444 #developer 1's ip
allow from 222.222.333.444 #developer 2's ip
#etc.. for other developers
</Directory>
子句中包含选择列表列;你可以这样做
GROUP BY
答案 2 :(得分:1)
我不知道这对你有用,因为我对postgresql知之甚少。也不确定这是否会给你你想要的东西。但是,试一试。您只需要在using子句中包含building_count。
SELECT brgy_locat, municipali, bldg_name, bldg_type,
gridcode, building_count
FROM (SELECT brgy_locat, municipali, bldg_name, gridcode, bldg_type,
count( bldg_name) as building_count
FROM hi
GROUP BY 1, 2, 3, 4, 5) cnt_hi
FULL JOIN (SELECT brgy_locat, municipali,bldg_name, gridcode, bldg_type,
count(bldg_name) as building_count
FROM med
GROUP BY 1, 2, 3, 4, 5) cnt_med
USING (brgy_locat, municipali, bldg_name,gridcode,bldg_type, building_count)
FULL JOIN (SELECT brgy_locat, municipali,bldg_name,gridcode, bldg_type,
count(bldg_name) as building_count
FROM low
GROUP BY 1, 2, 3, 4, 5) cnt_low
USING (brgy_locat, municipali, bldg_name, gridcode, bldg_type, building_count);
我不是在追求声誉。我刚刚更新了Rahul的回答。希望能帮助到你。干杯! :)