borders/db/create_osm_places_table.sql
Alexey Zakharenkov c31a2caf0a SQL formatting
2020-10-23 01:13:45 +03:00

86 lines
2.8 KiB
SQL

\c gis postgres
----------- Collect city polygons
CREATE TABLE osm_places AS
SELECT
osm_id,
place,
'polygon'::text AS g_type, -- geometry_type
max(CASE
WHEN regexp_replace(population, '[ .,]+', '', 'g') ~ '^\d+$'
THEN regexp_replace(population, '[ .,]+', '', 'g')::int
ELSE NULL
END
) AS population,
ST_Buffer(ST_Transform(ST_Collect(way),4326), 0) AS way,
coalesce(max("name"), max("name:en")) AS name
FROM planet_osm_polygon
WHERE place IN ('city', 'town', 'village', 'hamlet', 'isolated_dwelling')
GROUP BY osm_id, place;
----------- Collect city nodes
INSERT INTO osm_places
SELECT
osm_id,
place,
'point'::text AS g_type, -- geometry_type
CASE
WHEN regexp_replace(population, '[ .,]+', '', 'g') ~ '^\d+$'
THEN regexp_replace(population, '[ .,]+', '', 'g')::int
ELSE NULL
END AS population,
ST_Transform(way,4326) AS way,
coalesce("name", "name:en") AS name
FROM planet_osm_point
WHERE place IN ('city', 'town', 'village', 'hamlet', 'isolated_dwelling');
CREATE INDEX osm_places_gist_idx ON osm_places USING gist (way);
-- Update node population with polygon population where
-- the polygon duplicates the node and node has no population
UPDATE osm_places
SET population = q.max_population
FROM (
SELECT n.osm_id node_id,
greatest(p.population, n.population) max_population
FROM osm_places n, osm_places p
WHERE p.g_type='polygon'
AND n.g_type='point'
AND ST_Contains(p.way, n.way)
AND (strpos(n.name, p.name) > 0 OR strpos(p.name, n.name) > 0)
) q
WHERE g_type='point' AND osm_id = q.node_id;
-- Delete polygons where exists a node within it with the same name
DELETE FROM osm_places
WHERE g_type='polygon'
AND osm_id IN (SELECT p.osm_id
FROM osm_places n, osm_places p
WHERE p.g_type='polygon'
AND n.g_type='point'
AND ST_Contains(p.way, n.way)
AND (strpos(n.name, p.name) > 0 OR strpos(p.name, n.name) > 0));
-- Convert [multi]polygons to points - for further faster requests "is city in region"
ALTER TABLE osm_places ADD COLUMN center geometry;
UPDATE osm_places p
SET center = (
CASE
WHEN ST_Contains(way, ST_Centroid(way)) -- true for 99% of polygons
THEN ST_Centroid(way)
-- for the rest 1% of city polygons choose arbitrary point as a center
ELSE (
SELECT (ST_DumpPoints(way)).geom
FROM osm_places
WHERE osm_id = p.osm_id
LIMIT 1
)
END);
CREATE INDEX osm_places_center_gist_idx ON osm_places USING gist (center);
DROP INDEX osm_places_gist_idx;
ALTER TABLE osm_places DROP COLUMN way;