【发布时间】:2015-12-29 19:04:27
【问题描述】:
在安装了 PostGis 2.2.0 的 Postgres 9.5 数据库中,我有两张带有几何数据(点)的表,我想将一张表中的点分配给来自另一张表的点,但我不希望 buildings.gid 被分配两次。一旦分配了一个buildings.gid,就不应将其分配给另一个pvanlagen.buildid。
表定义
buildings:
CREATE TABLE public.buildings (
gid numeric NOT NULL DEFAULT nextval('buildings_gid_seq'::regclass),
osm_id character varying(11),
name character varying(48),
type character varying(16),
geom geometry(MultiPolygon,4326),
centroid geometry(Point,4326),
gembez character varying(50),
gemname character varying(50),
krsbez character varying(50),
krsname character varying(50),
pv boolean,
gr numeric,
capac numeric,
instdate date,
pvid numeric,
dist numeric,
CONSTRAINT buildings_pkey PRIMARY KEY (gid)
);
CREATE INDEX build_centroid_gix
ON public.buildings
USING gist
(st_transform(centroid, 31467));
CREATE INDEX buildings_geom_idx
ON public.buildings
USING gist
(geom);
pvanlagen:
CREATE TABLE public.pvanlagen (
gid integer NOT NULL DEFAULT nextval('pv_bis2010_bayern_wgs84_gid_seq'::regclass),
tso character varying(254),
tso_number numeric(10,0),
system_ope character varying(254),
system_key character varying(254),
location character varying(254),
postal_cod numeric(10,0),
street character varying(254),
capacity numeric,
voltage_le character varying(254),
energy_sou character varying(254),
beginning_ date,
end_operat character varying(254),
id numeric(10,0),
kkz numeric(10,0),
geom geometry(Point,4326),
gembez character varying(50),
gemname character varying(50),
krsbez character varying(50),
krsname character varying(50),
buildid numeric,
dist numeric,
trans boolean,
CONSTRAINT pv_bis2010_bayern_wgs84_pkey PRIMARY KEY (gid),
CONSTRAINT pvanlagen_buildid_fkey FOREIGN KEY (buildid)
REFERENCES public.buildings (gid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT pvanlagen_buildid_uni UNIQUE (buildid)
);
CREATE INDEX pv_bis2010_bayern_wgs84_geom_idx
ON public.pvanlagen
USING gist
(geom);
查询
我的想法是在分配buildings.gid 时设置的buildings 表中添加boolean 列pv:
UPDATE pvanlagen
SET buildid=buildings.gid, dist='50'
FROM buildings
WHERE buildid IS NULL
AND buildings.pv is NULL
AND pvanlagen.gemname=buildings.gemname
AND ST_Distance(ST_Transform(pvanlagen.geom,31467)
,ST_Transform(buildings.centroid,31467))<50;
UPDATE buildings
SET pv=true
FROM pvanlagen
WHERE buildings.gid=pvanlagen.buildid;
我在buildings 中测试了 50 行,但申请所有这些行的时间太长。我有 3.200.000 个建筑物 和 260.000 个 PV。
应分配最近建筑物的gid。如果在平局的情况下,分配哪个gid 无关紧要。如果我们需要制定规则,我们可以取gid较低的建筑物。
50 米是作为一个限制。我使用了ST_Distance(),因为它返回的最小距离应该在 50 米以内。后来我多次提出,直到每个PV Anlage都被分配。
建筑物和 PV 被分配到各自的区域 (gemname)。这应该会使分配更便宜,因为我知道最近的建筑物必须在同一区域内 (gemname)。
我在以下反馈后尝试了此查询:
UPDATE pvanlagen p1
SET buildid = buildings.gid
, dist = buildings.dist
FROM (
SELECT DISTINCT ON (b.gid)
p.id, b.gid, b.dist::numeric
FROM (
SELECT id, ST_Transform(geom, 31467)
FROM pvanlagen
WHERE buildid IS NULL -- not assigned yet
) p
, LATERAL (
SELECT b.gid, ST_Distance(ST_Transform(p1.geom, 31467), ST_Transform(b.centroid, 31467)) AS dist
FROM buildings b
LEFT JOIN pvanlagen p1 ON p1.buildid = b.gid
WHERE p1.buildid IS NULL
AND b.gemname = p1.gemname
ORDER BY ST_Transform(p1.geom, 31467) <-> ST_Transform(b.centroid, 31467)
LIMIT 1
) b
ORDER BY b.gid, b.dist, p.id -- tie breaker
) x, buildings
WHERE p1.id = x.id;
但它返回0 rows affected in 234 ms execution time。
我哪里错了?
【问题讨论】:
-
@ErwinBrandstetter 表定义已更新。再次感谢您的帮助!
-
考虑更新的解决方案。
-
@ErwinBrandstetter 新查询运行,但它设置了
buildid=sub.pv_gid,这实际上是 pvanlage 本身的确切 gid。不应该是SET build.id=sub.b_gid吗? -
是的,这是一个错字。已修复,谢谢。
标签: sql postgresql duplicates postgis knn