<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de-CH">
	<id>https://giswiki.ch/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zpang</id>
	<title>Geometa Lab OST - Benutzerbeiträge [de-ch]</title>
	<link rel="self" type="application/atom+xml" href="https://giswiki.ch/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zpang"/>
	<link rel="alternate" type="text/html" href="https://giswiki.ch/Spezial:Beitr%C3%A4ge/Zpang"/>
	<updated>2026-05-02T12:39:53Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>https://giswiki.ch/index.php?title=PostGIS_-_Tipps_und_Tricks&amp;diff=38252</id>
		<title>PostGIS - Tipps und Tricks</title>
		<link rel="alternate" type="text/html" href="https://giswiki.ch/index.php?title=PostGIS_-_Tipps_und_Tricks&amp;diff=38252"/>
		<updated>2012-02-15T09:15:14Z</updated>

		<summary type="html">&lt;p&gt;Zpang: /* PostGIS und Rasterdaten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Siehe auch: &lt;br /&gt;
* [[PostGIS]], [[PostGIS-Beispiele]] und [[PostGIS Snippets]]&lt;br /&gt;
* [[GISpunkt-Seminar_PostGIS]] &lt;br /&gt;
* [[PostgreSQL]], [[PostgreSQL - Tipps und Tricks]]&lt;br /&gt;
* Weitere Tipps und Tricks findet man im [http://spatialdbadvisor.com/postgis_tips_tricks SpatialDBAdvisor Blog für PostGIS]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tutorial zum Erstellen einer PostGIS-Datenbank ==&lt;br /&gt;
&lt;br /&gt;
Quelle: [http://www.bostongis.com/?content_name=postgis_tut01 BostonGIS].&lt;br /&gt;
&lt;br /&gt;
Erläuterungen: &amp;quot;shell&amp;gt;&amp;quot; ist der Prompt einer DOS- oder Linux-Shell. &amp;quot;gisdb=#&amp;quot; ist der Prompt von psql, eingeloggt als gisdb-User.&lt;br /&gt;
&lt;br /&gt;
;PostGIS-Versionen kontrollieren:&lt;br /&gt;
* PostgreSQL-Version: SELECT version();&lt;br /&gt;
* PostGIS-Version: &lt;br /&gt;
  SELECT postgis_full_version(); -- (bei aktiver Datenbank)&lt;br /&gt;
* sonst template kontrollieren?&lt;br /&gt;
&lt;br /&gt;
;PostGIS-Datenbank erzeugen (Name gisdb):&lt;br /&gt;
* Zur Vorbereitung: User &#039;gisdb&#039; erzeugen: &lt;br /&gt;
  shell&amp;gt; createuser -a -D gisdb&lt;br /&gt;
    oder&lt;br /&gt;
  shell&amp;gt; createuser -s -D -U postgres gisdb&lt;br /&gt;
&lt;br /&gt;
* Datenbank &#039;gisdb&#039; mit Template &#039;template_postgis&#039; und User &#039;gisdb&#039; erzeugen:&lt;br /&gt;
  shell&amp;gt; createdb -O gisdb -T template_postgis -U postgres gisdb description&lt;br /&gt;
&lt;br /&gt;
* Session und Grants festlegen: &lt;br /&gt;
  shell&amp;gt; psql -U postgres template1&lt;br /&gt;
  template1=# \c gisdb&lt;br /&gt;
  You are now connected to database &amp;quot;gisdb&amp;quot;.&lt;br /&gt;
  gisdb=# GRANT ALL ON TABLE geometry_columns TO postgres,public;&lt;br /&gt;
  GRANT&lt;br /&gt;
  gisdb=# GRANT ALL ON TABLE spatial_ref_sys TO postgres,public;&lt;br /&gt;
  GRANT&lt;br /&gt;
&lt;br /&gt;
* DB-Projektion (default SRID=-1) vormerken:&lt;br /&gt;
  gisdb=# select srid, srtext, proj4text from spatial_ref_sys where srtext ILIKE &#039;%Massachusetts%&#039;;&lt;br /&gt;
&lt;br /&gt;
;Download vornehmen:&lt;br /&gt;
* Downloaden: ftp://data.massgis.state.ma.us/pub/shape/state/towns.exe&lt;br /&gt;
* Auspacken und überprüfen:&lt;br /&gt;
  shell&amp;gt; unzip towns.exe&lt;br /&gt;
  shell&amp;gt; ogrinfo -so -al towns_poly.shp&lt;br /&gt;
&lt;br /&gt;
;Shapefile in PostGIS laden:&lt;br /&gt;
Shapefile nach SQL konvertieren: (-S erzeugt &#039;single&#039; Polygone (was shapefiles sind) und keine Multipolygone):&lt;br /&gt;
  shell&amp;gt; shp2pgsql -s 26986 -S TOWNS_POLY towns &amp;gt;towns_poly.sql&lt;br /&gt;
   oder &lt;br /&gt;
  shell&amp;gt; shp2pgsql -s 4326 -W latin1 Kantone_WGS84 kantone &amp;gt;kantone.sql&lt;br /&gt;
&lt;br /&gt;
;SQL-Daten in PostGIS laden: (&#039;2&amp;gt;towns_psql_error.txt&#039; leitet Error-Meldungen in eine Datei um):&lt;br /&gt;
  shell&amp;gt; psql -d gisdb -h localhost -U gisdb -f towns_poly.sql &amp;gt;towns_psql_log.txt 2&amp;gt;towns_psql_error.txt&lt;br /&gt;
   oder&lt;br /&gt;
  shell&amp;gt; psql -U postgres -d gisdb2 -f kantone.sql&lt;br /&gt;
&lt;br /&gt;
Beim Import können u.a. Topologie-Fehler zum Vorschein kommen (&amp;quot;Error: geometry contains non-closed rings&amp;quot;). Solche Geometrien werden nicht importiert.&lt;br /&gt;
&lt;br /&gt;
;PostGIS-Index erzeugen und Installation überprüfen: &lt;br /&gt;
PostGIS-Index erzeugen:&lt;br /&gt;
  shell&amp;gt; psql -U gisdb&lt;br /&gt;
  gisdb=# CREATE INDEX idx_towns_the_geom ON towns USING gist(the_geom);&lt;br /&gt;
  gisdb=# CREATE INDEX idx_towns_town ON towns USING btree(town);&lt;br /&gt;
&lt;br /&gt;
PostGIS-DB-Installation überprüfen:&lt;br /&gt;
  gisdb=# SELECT extent(the_geom) FROM towns WHERE town = &#039;BOSTON&#039;;&lt;br /&gt;
  gisdb=# SELECT area(geomunion(the_geom)) FROM towns WHERE town = &#039;BOSTON&#039;;&lt;br /&gt;
  gisdb=# SELECT town,astext(transform(the_geom,4326)) FROM towns WHERE town = &#039;BOSTON&#039;; &lt;br /&gt;
  gisdb=# SELECT count(town) FROM towns WHERE town = &#039;BOSTON&#039;;&lt;br /&gt;
  gisdb=# SELECT st_askml(geomunion(transform(the_geom,4326))) AS the_geom FROM towns WHERE town = &#039;BOSTON&#039;;&lt;br /&gt;
&lt;br /&gt;
;PostGIS-DB/-Tabelle löschen:&lt;br /&gt;
* PostGIS-DB:&lt;br /&gt;
  shell&amp;gt; dropdb gisdb&lt;br /&gt;
* Tabelle löschen inkl. aller Einträge in den &amp;quot;Systemtabellen&amp;quot;:&lt;br /&gt;
  abhängigkeiten in den &#039;Ref-System&#039;-Tabellen?&lt;br /&gt;
&lt;br /&gt;
== Shapefiles in PostGIS importieren (shp2pgsql) ==&lt;br /&gt;
Man beachte beim Import von Shapefiles das .prj File. Ohne weitere Angaben wird &lt;br /&gt;
der SRID auf -1 gesetzt. Siehe SRID ([http://thesteve0.wordpress.com/2007/10/08/updating-projections-and-postgis/ Quelle]).&lt;br /&gt;
&lt;br /&gt;
Shapefile-Daten in Datenbank geo1 laden:&lt;br /&gt;
  % shp2pgsql -s 21781 -I -W ISO-8859-1 gemeinden public.gemeinden &amp;gt; gemeinden.sql&lt;br /&gt;
  % psql -d geo1 -U geo1 -f gemeinden.sql&lt;br /&gt;
&lt;br /&gt;
Eine Alternative zu shp2pgsql ist ogr2ogr von [[OGR]].&lt;br /&gt;
&lt;br /&gt;
== PostGIS-Daten laden ==&lt;br /&gt;
&lt;br /&gt;
* Mittels (mit PostGIS ausgeliefertem) Kommandozeilen-Tool &#039;shp2pgsql&#039;. &lt;br /&gt;
* Mittels INSERT und WKT oder Konstruktoren (vgl. Snippet &amp;quot;Creating Geometry (...) Types&amp;quot; unten).&lt;br /&gt;
&lt;br /&gt;
== PostGIS-Daten darstellen ==&lt;br /&gt;
&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
* Lokal, mittels Desktop GIS:&lt;br /&gt;
** [[QGIS]]&lt;br /&gt;
** [[OpenJUMP]]&lt;br /&gt;
** GDV Spatial Commander [http://www.gdv.com/down/scommander.php]&lt;br /&gt;
** gvSIG [http://www.gvsig.gva.es/index.php?id=gvsig&amp;amp;L=2] gvSIG Wiki [http://webmapping.info/mwgvsig/index.php?title=Hauptseite]&lt;br /&gt;
** etc.&lt;br /&gt;
* über Webapplikationen ([[WMS]]):&lt;br /&gt;
** [[GeoServer]]&lt;br /&gt;
** [[UMN MapServer]]&lt;br /&gt;
** [[ArcGIS]] Server&lt;br /&gt;
&lt;br /&gt;
=== PostGIS und KML ===&lt;br /&gt;
&lt;br /&gt;
PostGIS kennt die Funktion ST_AsKML(), die eine Geometrie KML-konform ausgibt. Allerdings werden nur diejenigen KML-Elemente der Geometrie selbst ausgegeben. Kopf- und Fusszeile des KML-Dokuments muss man selber hinzufügen. Dazu erzeugen wir nun eine Funktion askmldoc, die ein gültiges KML-Dokument ausgibt:&lt;br /&gt;
&lt;br /&gt;
  CREATE OR REPLACE FUNCTION askmldoc(name text, description text, the_geom geometry) RETURNS text AS $$&lt;br /&gt;
  DECLARE&lt;br /&gt;
    result text;&lt;br /&gt;
  BEGIN&lt;br /&gt;
    result := &#039;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;kml xmlns=&amp;quot;http://www.opengis.net/kml/2.2&amp;quot;&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;Document&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;name&amp;gt;&#039; || name || &#039;&amp;lt;/name&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;description&amp;gt;&#039; || description || &#039;&amp;lt;/description&amp;gt;&#039; || E&#039;\n\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;Style id=&amp;quot;defaultStyle&amp;quot;&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;  &amp;lt;LineStyle&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;    &amp;lt;color&amp;gt;ff00ff00&amp;lt;/color&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;    &amp;lt;width&amp;gt;1&amp;lt;/width&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;  &amp;lt;/LineStyle&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;  &amp;lt;PolyStyle&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;    &amp;lt;color&amp;gt;5f00ff00&amp;lt;/color&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;  &amp;lt;/PolyStyle&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;/Style&amp;gt;&#039; || E&#039;\n\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;Placemark&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;styleUrl&amp;gt;#defaultStyle&amp;lt;/styleUrl&amp;gt;&#039; || E&#039;\n&#039;;&lt;br /&gt;
          result := result || ST_AsKML(the_geom) || E&#039;\n&#039;;&lt;br /&gt;
          result := result || &lt;br /&gt;
                    &#039;&amp;lt;/Placemark&amp;gt;&#039; || E&#039;\n\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;/Document&amp;gt;&#039; || E&#039;\n&#039; ||&lt;br /&gt;
                    &#039;&amp;lt;/kml&amp;gt;&#039;;&lt;br /&gt;
  RETURN result;&lt;br /&gt;
  END;&lt;br /&gt;
  $$ LANGUAGE plpgsql;&lt;br /&gt;
&lt;br /&gt;
Exportieren Sie damit die Geodaten in der Tabelle, z.B. mit folgendem Befehl auf der System-Kommandozeile (cmd):&lt;br /&gt;
&lt;br /&gt;
 % psql -A -t -d gisdb -c &amp;quot;SELECT askmldoc(&#039;MyTable&#039;, &#039;A Comment...&#039;, the_geom) FROM mytable WHERE gid=1;&amp;quot; -o mykmlfile.kml&lt;br /&gt;
&lt;br /&gt;
=== PostGIS und Google Earth === &lt;br /&gt;
&lt;br /&gt;
PostGIS über http-Tool mit Google Earth verknüpfen:&lt;br /&gt;
* [http://cse-mjmcl.cse.bris.ac.uk/blog/2006/05/27/1148737394599.html mit Java, GML und Google Maps] - Rendering roads on Google Maps using Java and PostGIS.&lt;br /&gt;
* [http://www.thetimoneygroup.net/foss/ thetimoneygroup.net] - On-the-Fly Spatial Analysis With PostGIS and Google Earth.&lt;br /&gt;
* ([http://www.oracle.com/technology/pub/articles/schalk-googlemaps.html mit Oracle XML-DB]).&lt;br /&gt;
&lt;br /&gt;
Von PostGIS direkt nach Google Earth:&lt;br /&gt;
&lt;br /&gt;
* Man starte psql (Beispiel mit Box um Victoria, BC, Kanada):&lt;br /&gt;
&lt;br /&gt;
  -- Set output to unaligned&lt;br /&gt;
  \a&lt;br /&gt;
  -- Show only tuples&lt;br /&gt;
  \t&lt;br /&gt;
  -- Dump query to a file&lt;br /&gt;
  \o my_kml_file.kml&lt;br /&gt;
  -- Run your query&lt;br /&gt;
  SELECT askml(&#039;my_line&#039;, &#039;description&#039;, &#039;SRID=3005;LINESTRING( 1190000&lt;br /&gt;
  390000, 1200000 390000, 1200000 380000, 1190000 380000, 1190000 390000&lt;br /&gt;
  )&#039;::geometry);&lt;br /&gt;
  -- Flush output your file and close the output stream&lt;br /&gt;
  \o&lt;br /&gt;
&lt;br /&gt;
* Dann Doppelklick auf die [[KML]]-Datei und [[Google Earth]] startet! &lt;br /&gt;
* Hinweis: Das KML muss ev. mit KML-Kopf und -Fuss ergänzt werden.&lt;br /&gt;
* Beispiel für einen Ausschnitt der Schweiz:&lt;br /&gt;
  SELECT AsKML(&#039;the_geom&#039;, &lt;br /&gt;
               &#039;SRID=21781;LINESTRING(480000 300000, 835000 300000, 835000 70000, 480000 70000, 480000 300000)&#039;::geometry&lt;br /&gt;
         );&lt;br /&gt;
* Beispiel für gisdb:&lt;br /&gt;
  SELECT ST_AsKML(geomunion(transform(the_geom,4326))) as the_geom from towns where town=&#039;BOSTON&#039;;&lt;br /&gt;
&lt;br /&gt;
== ST_Relate ==&lt;br /&gt;
&lt;br /&gt;
Documentation:&lt;br /&gt;
* Strobl paper&lt;br /&gt;
* PostGIS documentation ch04&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
  ST_Relate(geom_a, geom_b, &#039;&amp;lt;&amp;lt;param&amp;gt;&amp;gt;&#039;)&lt;br /&gt;
  ...&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
* ST_Contains(polygon_a, polygon_b) =&amp;gt; ST_Relate(.., .., &#039;****1****&#039;)&lt;br /&gt;
* ST_Crosses&lt;br /&gt;
* ST_Intersects&lt;br /&gt;
* ST_Touches&lt;br /&gt;
&lt;br /&gt;
== PostGIS und Rasterdaten ==&lt;br /&gt;
&lt;br /&gt;
Ab PostGIS Version 2.0 (geplant 1. Quartal 2011) gibt es neu einen Raster-Datentyp. &lt;br /&gt;
&lt;br /&gt;
Siehe [[PostGIS Raster]].&lt;br /&gt;
&lt;br /&gt;
== PostGIS und Koordinatenreferenzsystem-Angaben ==&lt;br /&gt;
Der SRID (projection identifier) wird an drei Orten verwaltet:&lt;br /&gt;
* In der geometry column: select SRID(the_geom) from mytable limit 5;&lt;br /&gt;
* As a constraint on the table for the geometry column: \d mytable&lt;br /&gt;
* In the geometry_columns system table: select * from geometry_columns;&lt;br /&gt;
&lt;br /&gt;
Mit der Methode UpdateGeometrySRID([&amp;lt;schema_name&amp;gt;], &amp;lt;table_name&amp;gt;, &amp;lt;column_name&amp;gt;, &amp;lt;srid&amp;gt;) kann man die Kolonne aktualisieren.&lt;br /&gt;
&lt;br /&gt;
Das wohl bekannteste Koordinatenreferensystem ist wohl WGS 84 (long/lat), das von [[GPS]] und [[KML]] geprägt ist und den Identifier &#039;EPSG:4326&#039; hat.&lt;br /&gt;
&lt;br /&gt;
Liste von SRID/SRS/CRS: http://www.spatialreference.org/&lt;br /&gt;
&lt;br /&gt;
Beim Aufruf von GDAL/OGR wird die GDAL_DATA environment Variable benötigt.&lt;br /&gt;
&lt;br /&gt;
== Benutzerdefinierte PostgreSQL/PostGIS-Funktionen ==&lt;br /&gt;
&lt;br /&gt;
Implementiert als sog. &#039;Stored Procedures&#039;.&lt;br /&gt;
&lt;br /&gt;
Siehe auch [[PostGIS-Beispiele]].&lt;br /&gt;
&lt;br /&gt;
=== Eliminate sliver polygons ===&lt;br /&gt;
&lt;br /&gt;
Given a polygon table that has many small areas and holes. How to remove &amp;quot;small&amp;quot; areas and holes (smaller than a given area in m2)? &lt;br /&gt;
&lt;br /&gt;
Remarks: &lt;br /&gt;
* Similar like the ELIMINATE command in [[ArcGIS]].&lt;br /&gt;
* See also CLEAN topology&lt;br /&gt;
&lt;br /&gt;
  CREATE OR REPLACE FUNCTION Filter_Rings(geometry,float)&lt;br /&gt;
  RETURNS geometry AS&lt;br /&gt;
  $$&lt;br /&gt;
  SELECT ST_MakePolygon(c.outer_ring, d.inner_rings) as final_geom&lt;br /&gt;
   FROM (/* Get outer ring of polygon */&lt;br /&gt;
         SELECT ST_ExteriorRing(b.the_geom) as outer_ring&lt;br /&gt;
           FROM (SELECT (ST_DumpRings($1)).geom As the_geom, path(ST_DumpRings($1)) as path) b&lt;br /&gt;
           WHERE b.path[1] = 0 /* ie the outer ring */&lt;br /&gt;
         ) c,&lt;br /&gt;
        (/* Get all inner rings &amp;gt; a particular area */&lt;br /&gt;
         SELECT ST_Accum(ST_ExteriorRing(b.the_geom)) as inner_rings&lt;br /&gt;
           FROM (SELECT (ST_DumpRings($1)).geom As the_geom, path(ST_DumpRings($1)) as path) b&lt;br /&gt;
           WHERE b.path[1] &amp;gt; 0 /* ie not the outer ring */&lt;br /&gt;
             AND ST_Area(b.the_geom) &amp;gt; $2&lt;br /&gt;
         ) d&lt;br /&gt;
  $$&lt;br /&gt;
  LANGUAGE &#039;sql&#039; IMMUTABLE;&lt;br /&gt;
&lt;br /&gt;
Usage example: &lt;br /&gt;
  % SELECT ST_AsText( &lt;br /&gt;
    Filter_Rings( &lt;br /&gt;
      ST_PolyFromText(&lt;br /&gt;
        &#039;POLYGON((10 10,10 20,20 20,20 10,10 10),(0 0,0 1,1 1,1 0,0 0),(5 5,5 7,7 7,7 5,5 5))&#039;&lt;br /&gt;
      ) ,1::float&lt;br /&gt;
    )&lt;br /&gt;
  );&lt;br /&gt;
  % &amp;quot;POLYGON((10 10,10 20,20 20,20 10,10 10),(5 5,5 7,7 7,7 5,5 5))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Shorter alternative to Filter_Rings:&lt;br /&gt;
&lt;br /&gt;
  CREATE OR REPLACE FUNCTION Filter_Rings2(geometry,float) RETURNS geometry AS&lt;br /&gt;
  $$ SELECT ST_BuildArea(ST_Collect(a.geom)) as final_geom&lt;br /&gt;
          FROM ST_DumpRings($1) AS a&lt;br /&gt;
            WHERE a.path[1] = 0 OR&lt;br /&gt;
                  (a.path[1] &amp;gt; 0 AND ST_Area(a.geom) &amp;gt; $2)&lt;br /&gt;
  $$&lt;br /&gt;
  LANGUAGE &#039;sql&#039; IMMUTABLE;&lt;br /&gt;
&lt;br /&gt;
With following restrictions: Possibly slower and squashes 3D geometries to 2D.&lt;br /&gt;
(Source: http://postgis.refractions.net/pipermail/postgis-users/2009-January/022325.html)&lt;br /&gt;
&lt;br /&gt;
=== Clean topology ===&lt;br /&gt;
&lt;br /&gt;
Remarks: Similar to [[ArcGIS]]&#039; CLEAN. See also Eliminate sliver polygons.&lt;br /&gt;
&lt;br /&gt;
See:&lt;br /&gt;
* Function cleanGeometry(): http://trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons&lt;br /&gt;
* Topology function: http://trac.osgeo.org/postgis/wiki/UsersWikiPostgisTopology&lt;br /&gt;
&lt;br /&gt;
== PostGIS optimieren ==&lt;br /&gt;
&lt;br /&gt;
Siehe auch: &lt;br /&gt;
* [[PostgreSQL - Tipps und Tricks#PostgreSQL_optimieren]] (tuning).&lt;br /&gt;
* [http://www.foss4g2007.org/presentations/view.php?abstract_id=117 Tips for the PostGIS Power User ]&lt;br /&gt;
&lt;br /&gt;
Version:&lt;br /&gt;
* 1.4 and GEOS 3.1 will bring prepared geometries which will make things faster.&lt;br /&gt;
&lt;br /&gt;
Reorder on disk:&lt;br /&gt;
* import the data (into a temporary table) &lt;br /&gt;
* and then sort the data using some sort of spatial key. A centroid should be OK but consider using a larger bucket such as a gridded area.&lt;br /&gt;
  &amp;gt; CREATE TABLE gis_roads &lt;br /&gt;
      AS SELECT * FROM tmp_gis_roads &lt;br /&gt;
      ORDER BY CENTROID(the_geom);&lt;br /&gt;
&lt;br /&gt;
Cluster on disk:&lt;br /&gt;
  &amp;gt; CREATE INDEX idx_mytable_the_ON mytable &lt;br /&gt;
      USING GIST(the_geom);&lt;br /&gt;
  &amp;gt; CLUSTER mytable &lt;br /&gt;
      USING idx_mytable_the_geom;&lt;br /&gt;
&lt;br /&gt;
Don&#039;ts:&lt;br /&gt;
* Don&#039;t use just one big diagonal lines. Break it down because one diagonal line has a huge bounding box (which is what the index works on) while  20 equivalent shorter lines have a much smaller combined box area. &lt;br /&gt;
* Don&#039;t use this construction: ST_Intersects(Buffer(GeomA, D), GeomB) Use this one: ST_DWithin(GeomA, GeomB, D)&lt;br /&gt;
&lt;br /&gt;
== Weitere Beispiele ==&lt;br /&gt;
&lt;br /&gt;
Siehe auch: &lt;br /&gt;
* [[PostGIS Snippets]]&lt;br /&gt;
* [[PostGIS-Beispiele]] mit British-Columbia-Daten&lt;br /&gt;
* [http://trac.osgeo.org/postgis/wiki/UsersWikiMain PostGIS-Wiki]&lt;br /&gt;
&lt;br /&gt;
== Fragen und Antworten ==&lt;br /&gt;
&lt;br /&gt;
;Was ist der Unterschied von geometry und geography type?: Geography type besteht aus geografischen Koordinaten (z.B. lat/lon) und wird für grossflächige Daten verwendet, die z.B. &amp;quot;länderübergreifend&amp;quot; sind.&lt;br /&gt;
&lt;br /&gt;
;Wie wird ein Geometrie-Attribut erzeugt?: als separates Statement, gleich nach CREATE TABLE... Mit AddGeometryColumn. Ab PostGIS 1.5 ist es endlich möglich, den konkreten Geometrie-Typ direkt im CREATE STATEMENT anzugeben.&lt;br /&gt;
&lt;br /&gt;
;Was bedeutet SRID und wie kann man das ändern?: SRID bedeutet Spatial Reference ID und ist ein Fremdschlüssel zum [[Koordinatenreferenzsystem]]. SRID information is stored *both* in the geometry_columns table (srid column), and inside each geometry itself. Ist opbligatorischer Parameter u.a. von AddGeometryColumn oder beim Geometrie-Erzeugen. Kann mit UpdateGeometrySRID geändert werden.&lt;br /&gt;
&lt;br /&gt;
;Was bedeutet der Error &amp;quot;addgeometrycolumn(...) does not exist&amp;quot;?: Die PostGIS-Funktionen sind nicht geladen. Man installiere die PostGIS-Erweiterung (falls nicht schon geschehen) und erzeuge eine neue PostGIS-Datenbank (siehe &amp;quot;Wie erzeugt man eine neue PostGIS-Datenbank?&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
;Wie erzeugt man eine neue PostGIS-Datenbank?: 1. Falls noch keine &#039;normale&#039; (=Nicht-GIS-) Datenbank vorhanden ist, &amp;quot;create a new database and choose the template_postgis as your template&amp;quot;. 2. Falls eine &#039;normale&#039; Datenbank mit Tabellen etc. bereits existiert, &amp;quot;spatially enable your database by running the following two SQL files: a) Postgresql\8.2\share\contrib\lwpostgis.sql and b) Postgresql\8.2\share\contrib\spatial_ref_sys.sql. lwpostgis.sql benötigt plpgsql language support installed (Syntax: createlang plpgsql yourexistingdb).&lt;br /&gt;
&lt;br /&gt;
;Was ist das für eine Zahl, die ST_distance() zurückgibt?: Siehe [http://postgis.refractions.net/support/wiki/ PostGIS Wiki].&lt;br /&gt;
&lt;br /&gt;
;Was ist der Unterschied zwischen ST_Overlaps, ST_Crosses, ST_Intersects und ST_Contains?: Siehe [http://www.postgis.org/documentation/manual-1.5SVN/ST_Overlaps.html PostGIS-Doku. zu ST_Overlaps]. &lt;br /&gt;
&lt;br /&gt;
;Was ist der Unterschied zwischen ST_Extent und ST_Expand?: Siehe [http://www.bostongis.com/postgis_extent_expand_buffer_distance.snippet].&lt;br /&gt;
&lt;br /&gt;
;Was für Mass-Einheiten (units of measurement) benützen die PostGIS-Funktionen?: Siehe [http://postgis.refractions.net/support/wiki/ PostGIS Wiki].&lt;br /&gt;
&lt;br /&gt;
;Wie erhält man Distanz-Masse in Meter?: Siehe [http://postgis.refractions.net/support/wiki/ PostGIS Wiki].&lt;br /&gt;
&lt;br /&gt;
;Was sind die Grenzen der 3D-Typen und -Funktionen in PostGIS?: (1) 3D volumetric objects are not supported. (2) 3D non-volume are supported partly -- e.g. a 2D polygon in 3 d space, a line, point in 3d space. (3) Spatial relationships however only consider the spatial component of the x, y plane.&lt;br /&gt;
&lt;br /&gt;
;MySQL hat auch eine Spatial Extension und ist erst noch bei Internet-Service-Providern verbreiteter; was ist der Unterschied zu PostGIS?: Drei Gründe: (1) Operationen werden nur mittels Bounding-Box gemacht ([http://dev.mysql.com/doc/refman/5.1/en/functions-that-test-spatial-relations hips-between-geometries.html], (2) es gibt keine Unterstützung für Koordinatensysteme, (3) die Spatial Extension ist praktisch eine One-Man-Show.&lt;br /&gt;
&lt;br /&gt;
== Snippets ==&lt;br /&gt;
&lt;br /&gt;
=== Get area of a polygon which has SRID EPSG:4326 (WGS84/GPS) ===&lt;br /&gt;
&lt;br /&gt;
All area functions are squared by definition.&lt;br /&gt;
But a sq degree varies in its area depending on latitude.&lt;br /&gt;
Transform your data using a SRID referring to an equal-area (or near enough to&lt;br /&gt;
equal area for your purposes) projection in the query for area:&lt;br /&gt;
&lt;br /&gt;
  -- Get area from a geometry given the geometry is in 4326.&lt;br /&gt;
  % SELECT ST_Area2d(ST_transform(geometry, &amp;lt;SRID&amp;gt;));&lt;br /&gt;
&lt;br /&gt;
=== Creating Geometry and Geography Types ===&lt;br /&gt;
Allowed and non-functioning constructors for creating geometry types (Varianten für geometry types):&lt;br /&gt;
  /*0*/ SELECT ST_AsEWKT(ST_GeomFromText(&#039;POINT(-71.06 42.28)&#039;))           -- &#039;&#039;&#039;Preferred simplest text form without SRID&#039;&#039;&#039;&lt;br /&gt;
  /*1*/ SELECT ST_AsEWKT(ST_GeomFromText(&#039;POINT(-71.06 42.28)&#039;, 4326))     -- &#039;&#039;&#039;Preferred for text form with SRID&#039;&#039;&#039;&lt;br /&gt;
  /*2*/ SELECT ST_AsEWKT(ST_GeomFromText(&#039;SRID=4326;POINT(-71.06 42.28)&#039;)) -- Note: srid &#039;inline&#039;&lt;br /&gt;
  /*3*/ SELECT ST_AsEWKT(ST_GeomFromEWKT(&#039;SRID=4326;POINT(-71.06 42.28)&#039;)) -- Alternative to ST_GeomFromText()&lt;br /&gt;
  /*4*/ SELECT ST_AsEWKT(&#039;SRID=4326;POINT(-71.06 42.28)&#039;::geometry)        -- With cast; prefer *1*/ST_GeomFromText&lt;br /&gt;
  /*5*/ SELECT ST_AsEWKT(ST_SetSRID(&#039;POINT(-71.06 42.28)&#039;::geometry,4326)) -- With cast; prefer *1*/ST_GeomFromText&lt;br /&gt;
  /*6*/ SELECT ST_AsEWKT(ST_MakePoint(-71.06, 42.28, 4326))                -- &#039;&#039;&#039;Preferred symbolic form&#039;&#039;&#039; (Hint: returns WKT, not EWKT)&lt;br /&gt;
&lt;br /&gt;
Allowed and non-functioning constructors for creating geography types (Varianten für geography types):&lt;br /&gt;
  /*1*/  -- SELECT ST_AsEWKT(ST_GeogFromText(&#039;POINT(-71.06 42.28)&#039;, 4326))       -- ERROR: unknown ST_GeogFromText()&lt;br /&gt;
  /*2a*/ -- SELECT ST_AsEWKT(ST_GeogFromText(&#039;SRID=4326;POINT(-71.06 42.28)&#039;))   -- ERROR: no ST_AsEWKT: why not?&lt;br /&gt;
  /*2b*/ SELECT ST_AsText(ST_GeogFromText(&#039;SRID=4326;POINT(-71.06 42.28)&#039;))      -- Preferred with srid &#039;inline&#039;; (Hint: ST_AsEWKT doesn&#039;t work)&lt;br /&gt;
  /*3*/  -- SELECT ST_AsText(ST_GeogFromEWKT(&#039;SRID=4326;POINT(-71.06 42.28)&#039;))   -- ERROR: no ST_GeogFromEWKT()&lt;br /&gt;
  /*4*/  SELECT ST_AsText(&#039;SRID=4326;POINT(-71.06 42.28)&#039;::geography)            -- With cast; prefer *1*; (Hint: ST_AsEWKT doesn&#039;t work)&lt;br /&gt;
  /*5*/  --- SELECT ST_AsText(ST_SetSRID(&#039;POINT(-71.06 42.28)&#039;::geography,4326)) -- ERROR: ok SetSRID w. geography unnecessary&lt;br /&gt;
  /*6*/  -- Equivalent to ST_MakePoint() for geography types missing.            -- .&lt;br /&gt;
&lt;br /&gt;
=== Extent of Database ===&lt;br /&gt;
&lt;br /&gt;
If you want to find out the EXTENT parameters of your database, run this command:&lt;br /&gt;
  # su postgres&lt;br /&gt;
  # psql -d &amp;lt;yourdatabase&amp;gt; -c &amp;quot;SELECT extent(geometry) FROM &amp;lt;yourtable&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;your...&amp;gt; with the relevant database and table names.&lt;br /&gt;
&lt;br /&gt;
=== Nearest Neighbors ===&lt;br /&gt;
&lt;br /&gt;
Find n (e.g. 5) nearest neighbors for given point coordinate (a classic query).&lt;br /&gt;
From &#039;[postgis-users] Find n Nearest Neighbors for given Point using PostGIS?&#039;.&lt;br /&gt;
&lt;br /&gt;
  CREATE TABLE geoname ( -- (from geonames.org) &lt;br /&gt;
    geoname varchar(255),&lt;br /&gt;
    geonameid integer,&lt;br /&gt;
    geom geometry&lt;br /&gt;
  );&lt;br /&gt;
  -- PRIMARY KEY UNIQUE BTREE index for geonameid&lt;br /&gt;
  &lt;br /&gt;
  UPDATE geoname SET geom = ST_SetSRID(ST_Point(longitude,latitude) 4326);&lt;br /&gt;
  ...&lt;br /&gt;
  CREATE INDEX geom_index ON geoname USING GIST (geom);) &lt;br /&gt;
  CLUSTER geom_index ON geoname;&lt;br /&gt;
&lt;br /&gt;
Possible solution (inspired by [http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_nearest_neighbor]):&lt;br /&gt;
&lt;br /&gt;
  SELECT &lt;br /&gt;
    start.asciiname, &lt;br /&gt;
    ende.asciiname, &lt;br /&gt;
    distance_sphere(start.geom,ende.geom) as distance&lt;br /&gt;
  FROM geoname AS start, geoname AS ende &lt;br /&gt;
  WHERE start.geonameid = 2950159 &lt;br /&gt;
    AND start.geonameid &amp;lt;&amp;gt; ende.geonameid &lt;br /&gt;
    AND ST_DWithin(start.geom, ende.geom, 30) &lt;br /&gt;
  ORDER BY distance LIMIT 5;&lt;br /&gt;
&lt;br /&gt;
There will be a KNNGIS index probably in PostgreSQL 9.1 which makes such queries even faster. It returns the found tupels in decreasing order until LIMIT without computing and sorting whole set before returning it. &lt;br /&gt;
&lt;br /&gt;
The way currently is to write a stored procedure that expands the search if it fails to get the number of results. So make a set returning function with the body something like this (pseudo code) and you should get good performance:&lt;br /&gt;
&lt;br /&gt;
  radius := 0.01; -- assuming degrees&lt;br /&gt;
  loop&lt;br /&gt;
   select into cnt count(*) from mytable&lt;br /&gt;
    where expand(mypnt, radius) &amp;amp;&amp;amp; the_geom limit 5;&lt;br /&gt;
   if found and cnt = 5 or radius &amp;gt; maxradius then&lt;br /&gt;
     for rr in select * from mytable&lt;br /&gt;
                 where expand(mypnt, radius) &amp;amp;&amp;amp; the_geom limit 5&lt;br /&gt;
       loop&lt;br /&gt;
         return rr;&lt;br /&gt;
       end loop;&lt;br /&gt;
     return;&lt;br /&gt;
   else&lt;br /&gt;
     radius := radius * 2;&lt;br /&gt;
   end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
&lt;br /&gt;
=== Select nearest point on polyline ===&lt;br /&gt;
&lt;br /&gt;
A user clicks somewhere on a polyline and we want to get the closest point that is part of the representation of the line. You can replace 0.01 with some other tolerance number to compensate for the fact that a person probably won&#039;t click right on the line.&lt;br /&gt;
&lt;br /&gt;
Ab PostGIS 1.3.5 (wegen generate_series() )?&lt;br /&gt;
  SELECT P.gid, P.geom As pclosest&lt;br /&gt;
  FROM (SELECT &lt;br /&gt;
    gid, &lt;br /&gt;
    ST_PointN(the_geom, generate_series(1, ST_NPoints(the_geom))) AS geom&lt;br /&gt;
  FROM point_table) AS P&lt;br /&gt;
  WHERE ST_Dwithin(P.geom, ST_SetSRID(ST_MakePoint(lon,lat),somesrid), 0.01)&lt;br /&gt;
&lt;br /&gt;
=== PostGIS views ===&lt;br /&gt;
&lt;br /&gt;
Q: I like to polygonize linestrings in a view to see the result in qgis. But qgis need gid. How can I create the gid column after an aggregate function in a view?&lt;br /&gt;
&lt;br /&gt;
A1. In postgresql 8.3 you can force oid creation if WITH OIDS is specified&lt;br /&gt;
when the table is created:&lt;br /&gt;
&lt;br /&gt;
  CREATE VIEW myview AS SELECT oid AS gid, the_geom FROM mytable;&lt;br /&gt;
&lt;br /&gt;
A2. Create a sequence and use then nextval(sequence_name) to get a primary key.&lt;br /&gt;
&lt;br /&gt;
A3. Grab the key from the underlying geometry table, &amp;amp; use it for a key column in your aggregate view, eg. &amp;quot;create view v1 as select min(key) as key&amp;quot; ...&lt;br /&gt;
&lt;br /&gt;
=== Standard direction for polylines ===&lt;br /&gt;
&lt;br /&gt;
Q: Is there a standard direction for polylines?&lt;br /&gt;
&lt;br /&gt;
A: There isn&#039;t a standard, but you can force your polygons into an orientation with ST_ForceRHR, which forces a clockwise orientation for exterior rings and anti-clockwise for interior rings.&lt;br /&gt;
&lt;br /&gt;
=== Portion of river geometry along administrative boundary ===&lt;br /&gt;
&lt;br /&gt;
Q: I have a rivers linestring table and a political boundaries (counties) table polygon. I am wishing to extract the portion of the river geometry that lies along a county border. Of course, these two layers don&#039;t have the same individual point precision, so I suspect some buffering is necessary.  &lt;br /&gt;
&lt;br /&gt;
A: See following SQL query:&lt;br /&gt;
&lt;br /&gt;
  intersection(&lt;br /&gt;
       buffer(exteriorring(geometryn(n.geom,1)),0.02),&lt;br /&gt;
       r.geom&lt;br /&gt;
  )&lt;br /&gt;
&lt;br /&gt;
So turn the county polygon into an exterior ring and then buffer it out a bit. Then see what portions of the river intersect that buffered polygon.&lt;br /&gt;
&lt;br /&gt;
=== Convert multipolygon to polygon ===&lt;br /&gt;
Q: How to convert multipolygon to polygon geometries&lt;br /&gt;
&lt;br /&gt;
A: If multipolygon only have one member, then st_geometryn(geom, 1) will do it. Otherwise, look at function st_dump().&lt;br /&gt;
&lt;br /&gt;
=== Getting all polygon&#039;s coordinates ===&lt;br /&gt;
&lt;br /&gt;
Q. Given a geometry attribute with polygons, how can one get all the polygon&#039;s coordinates (as a tupel set)? E.g. either &lt;br /&gt;
&lt;br /&gt;
  1 POINT(1 2)&lt;br /&gt;
  2 POINT(2 2)&lt;br /&gt;
  3 POINT(3 2)&lt;br /&gt;
  ...&lt;br /&gt;
... or even better: &lt;br /&gt;
      X    Y&lt;br /&gt;
  1  1     2&lt;br /&gt;
  2  2     2&lt;br /&gt;
  3  3     2&lt;br /&gt;
  ...&lt;br /&gt;
  &lt;br /&gt;
1. Maybe a &amp;quot;SELECT ST_AsText(polygon_column) FROM Table&amp;quot; is enough&lt;br /&gt;
&lt;br /&gt;
Output: POLYGON( (1 1, 2 2, 3 3) )&lt;br /&gt;
&lt;br /&gt;
2. &lt;br /&gt;
  SELECT &lt;br /&gt;
    DISTINCT ST_X(ST_POINTN(foo.lines, foo.index)) AS x,&lt;br /&gt;
    ST_Y(ST_POINTN(foo.lines, foo.index)) AS y &lt;br /&gt;
  FROM (SELECT thelines.lines, generate_series(1,thelines.n) AS index &lt;br /&gt;
          FROM (SELECT polys.geo AS lines, ST_NUMPOINTS(polys.geo) AS n &lt;br /&gt;
                  FROM (SELECT ST_BOUNDARY((ST_DUMP( the_geom )).geom) AS geo &lt;br /&gt;
                          FROM &amp;quot;YOURTABLE&amp;quot; WHERE YOURQUERY&lt;br /&gt;
                      ) AS polys&lt;br /&gt;
              ) AS thelines&lt;br /&gt;
       ) AS foo;&lt;br /&gt;
&lt;br /&gt;
  SELECT DISTINCT &lt;br /&gt;
  -- foo.index,&lt;br /&gt;
  ST_X(ST_POINTN(foo.lines, foo.index)) AS x,&lt;br /&gt;
  ST_Y(ST_POINTN(foo.lines, foo.index)) AS y &lt;br /&gt;
  FROM (SELECT thelines.lines, generate_series(1,thelines.n) AS index &lt;br /&gt;
          FROM (SELECT polys.geo AS lines, ST_NUMPOINTS(polys.geo) AS n &lt;br /&gt;
                  FROM (SELECT ST_BOUNDARY((ST_DUMP( the_geom )).geom) AS geo &lt;br /&gt;
                          FROM &amp;quot;gemeinden&amp;quot; WHERE gid=4 &lt;br /&gt;
                      ) AS polys&lt;br /&gt;
              ) AS thelines&lt;br /&gt;
       ) AS foo&lt;br /&gt;
&lt;br /&gt;
Should work for multipolygons and polygons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
3. You can import a plpgsql implementation of this until it&#039;s implemented in C (http://trac.osgeo.org/postgis/attachment/ticket/76/my_st_dump_points.2.sql).&lt;br /&gt;
[[Media:]]&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
  SELECT ST_AsText( (My_ST_DumpPoints( poly )).geom )&lt;br /&gt;
  FROM (&lt;br /&gt;
    SELECT &#039;POLYGON((0 0, 1 1, 1 0, 0 0))&#039;::geometry AS poly&lt;br /&gt;
  ) AS foo;&lt;br /&gt;
&lt;br /&gt;
  ST_AsText ------------&lt;br /&gt;
  POINT(0 0)&lt;br /&gt;
  POINT(1 1)&lt;br /&gt;
  POINT(1 0)&lt;br /&gt;
  POINT(0 0)&lt;br /&gt;
  (4 rows)&lt;br /&gt;
&lt;br /&gt;
=== Split a polygon to N linestrings ===&lt;br /&gt;
&lt;br /&gt;
Source: http://postgis.refractions.net/pipermail/postgis-users/2010-January/025818.html &lt;br /&gt;
&lt;br /&gt;
  CREATE TEMP TABLE mypolygontable AS&lt;br /&gt;
  SELECT&lt;br /&gt;
  &#039;MULTIPOLYGON(((0 0, 0 4, 4 4, 4 0, 0 0),&lt;br /&gt;
                 (1 1, 1 2, 2 2, 2 1, 1 1)),&lt;br /&gt;
                ((5 5, 5 6, 6 6, 6 5, 5 5))&lt;br /&gt;
               )&#039;::geometry geom;&lt;br /&gt;
&lt;br /&gt;
  -- make line segments from every startpoint and endpoint&lt;br /&gt;
  SELECT ST_AsText( ST_MakeLine(sp,ep) )&lt;br /&gt;
  FROM&lt;br /&gt;
    -- extract the endpoints for every 2-point line segment for each&lt;br /&gt;
  (SELECT&lt;br /&gt;
     ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,&lt;br /&gt;
     ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) as ep&lt;br /&gt;
   FROM&lt;br /&gt;
      -- extract the individual linestrings&lt;br /&gt;
     (SELECT (ST_Dump(ST_Boundary(geom))).geom&lt;br /&gt;
      FROM polygons&lt;br /&gt;
      ) AS linestrings&lt;br /&gt;
  ) AS segments;&lt;br /&gt;
&lt;br /&gt;
      st_astext&lt;br /&gt;
  ---------------------&lt;br /&gt;
  LINESTRING(0 0,0 4)&lt;br /&gt;
  LINESTRING(0 4,4 4)&lt;br /&gt;
  LINESTRING(4 4,4 0)&lt;br /&gt;
  LINESTRING(4 0,0 0)&lt;br /&gt;
  LINESTRING(1 1,1 2)&lt;br /&gt;
  LINESTRING(1 2,2 2)&lt;br /&gt;
  LINESTRING(2 2,2 1)&lt;br /&gt;
  LINESTRING(2 1,1 1)&lt;br /&gt;
  LINESTRING(5 5,5 6)&lt;br /&gt;
  LINESTRING(5 6,6 6)&lt;br /&gt;
  LINESTRING(6 6,6 5)&lt;br /&gt;
  LINESTRING(6 5,5 5)&lt;br /&gt;
 (12 rows)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More general solution: &lt;br /&gt;
* http://www.spatialdbadvisor.com/postgis_tips_tricks/128/exploding-a-linestring-or-polygon-into-individual-vectors-in-postgis/&lt;br /&gt;
&lt;br /&gt;
=== Aggregate linestrings ===&lt;br /&gt;
&lt;br /&gt;
Q. Trying to aggregate linestrings together based on their attributes and the fact that they are touching each other.&lt;br /&gt;
&lt;br /&gt;
A. There is a ST_Linemerge function that takes a collection of linestrings as an argument and merges them together into a multilinestring.&lt;br /&gt;
&lt;br /&gt;
With a table &amp;quot;thetable&amp;quot; having an &amp;quot;attrib&amp;quot; field and a &amp;quot;geom&amp;quot; field, one could write the query like this :&lt;br /&gt;
&lt;br /&gt;
  SELECT attrib, (st_dump(merged_geom)).geom&lt;br /&gt;
  FROM (&lt;br /&gt;
    SELECT attrib, ST_Linemerge(ST_Collect(geom)) AS merged_geom&lt;br /&gt;
    FROM thetable&lt;br /&gt;
    GROUP BY attrib&lt;br /&gt;
  ) AS subq;&lt;br /&gt;
&lt;br /&gt;
=== Polygons that don&#039;t overlap ===&lt;br /&gt;
&lt;br /&gt;
Q. I have a table with a MULTIPOLYGON field. Some of these records have self intersections and other problems that make ST_IsValid return false. The polygons overlap a lot and I wanted to generate another table that will be the union of all polygons. The table looks like: id, the_geom. What would be the best way to union all of the geometries into a new table where there is only POLYGONS that do not overlap?&lt;br /&gt;
&lt;br /&gt;
A. See SQL:&lt;br /&gt;
&lt;br /&gt;
  SELECT id, ST_Union(ST_Accum(CASE WHEN ST_IsValid(a.the_geom) = &#039;t&#039; THEN a.the_geom ELSE st_buffer(a.the_geom,0) end) AS the_geom&lt;br /&gt;
  FROM (SELECT id, the_geom&lt;br /&gt;
    FROM mytable&lt;br /&gt;
    WHERE the_geom IS NOT NULL&lt;br /&gt;
      AND geometrytype(the_geom) != &#039;GEOMETRYCOLLECTION&#039;&lt;br /&gt;
    UNION ALL&lt;br /&gt;
       SELECT gid, (ST_Dump(the_geom)).geom AS the_geom&lt;br /&gt;
         FROM mytable&lt;br /&gt;
         WHERE the_geom IS NOT NULL&lt;br /&gt;
           AND geometrytype(the_geom) = &#039;GEOMETRYCOLLECTION&#039;&lt;br /&gt;
       ) AS a;&lt;br /&gt;
&lt;br /&gt;
The split based on GEOMETRYCOLLECTION is that when I first tested the STR indexed ST_Union I found that performance was affected if the union set includes an mpoly.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:PostGIS]] [[Kategorie:HowTo]]&lt;/div&gt;</summary>
		<author><name>Zpang</name></author>
	</entry>
</feed>