-- =================================================================================== -- ALKIS-PostGIS Mapbender-Navigation und Buchauskunft für NorGIS-ALKIS-Importer -- =================================================================================== --Stand -- 2016-02-23 -- 2016-11-24 Index auf ax.person.nachnameoderfirma für WMS Flurstuecke_kommunal -- 2016-12-01 exp_csv: Fehlerkorrektur bei Entschlüsselung der Buchungsart -- Optimierte Version (ohne Doppelverbindung) -- ToDo: Auch den View "flst_an_strasse" möglist nicht in andere Views einbinden. -- Dafür die gesamte Struktur als UNION-View. -- Aufgabe: -- -- Die ALKIS-Navigation für Mapbender 2.7.4 arbeitet bisher mit der Datenbank-Struktur -- aus dem "Klassischen" Import mit Aufruf des Konvertres ogr2ogr aus einen Shellscript. -- -- Dabei wird ein PostProcessing (Nach-Konverter-Verarbeitung) durchgeführt, -- das Tabellen und Views bereit stellt, für einen schnellen Zugriff in -- Mapfile, Auskunft und Navigation. -- -- Dies Script soll eine Datenbank, die mit dem NorGIS-ALKIS-Importer geladen wurde -- für die Verwendung mit ALKIS-Navigation und Buchauskunft vorbereiten. -- Es ist jedoch eine speziell angepasste Version der NAV-PHP-Scripte notwendig. -- Alternative: -- Die bisher auch in der NAV verwendeten Tabellen "pp_flur", "pp_gemarkung", "pp_gemeinde" -- werden auch für eine "Übersichtskarte" benötigt (Gruppe "Gebiete" im Classic-Mapfile). -- Um diese zu bekommen müsste dieser Teil des klassischen Post-Processing auch in der -- NorGIS-Version ausgeführt würde. -- Siehe Script: "pp_gebiete.sql" (Füllen) und Teile von "pp_definition.sql" (DB-Struktur). -- T e s t / A n a l y s e -- ============================ /* -- Änderungswünsche an der norGIS-ALKIS-Importer Datenbankstruktur -- ----------------------------------------------------------------- 1. In den ALKIS-Tabellen "ax_historischesflurstueck" und "ax_historischesflurstueckohneraumbezug" sollten die Spalten "zaehler" und "nenner" das Format Integer statt Character haben. Beim Anzeigen wird eine "numerische" Sortierung erwartet (aufsteigende FS-Nummer). Da die Spalten linksbündig ohne führende Nullen gefüllt sind muss man bei jeder Abfrage eine Typenumwandlung "cast(.. AS integer)" durchführen um eine numerische Sortierung zu bekommen. 2. In den PostProcessing-Tabellen "gem_shl" und "gema_shl" sollten die Spalten als "character varying" definiert sein und NICHT mit Leerzeichen aufgefüllt werden. Derzeit muss man bei der Suche und Anzeige immer mit Subsring- und Trim-Funktionen arbeiten. 3. Die Gemarkungsnummer sollte einheitlich ohne vorangestelltes "Land" verwendet werden. In den ALKIS-Tabellen ist i.d.R. die Gemarkungsnummer 4stellig enthalten und land (2) in einem weiteren Feld. (ax_gemarkungsteilflur.gemarkung integer, ax_gemarkung.gemarkungsnummer character varying, ax_flurstueck.gemarkungsnummer character varying, usw. ..) In den Hilfstabellen wie "gema_shl.gemashl" wird Gemarkung aber 6stellig mit "land" davor gespeichert. Man muss in den Programmen dann mal das Land hinzufügen und mal abschneiden. */ -- D a t e n -- ============================ -- Die "Beziehungen" werden immer noch mit geladen, sind aber inzwischen überflüssig, -- weil jetzt Relationen zwischen den Tabellen definiert sind. TRUNCATE alkis_beziehungen; -- T a b e l l e n -- ============================ -- "pp_gemeinde" ersetzen -- ------------------------ -- "pp_gemeinde" ist eine optimierte Tabelle der Gemeinden aus dem Post-Processing der Classic-Variante. -- In der NAV eErsetzen durch: -- TABLE gem_shl ( -- gemshl character(32) NOT NULL, -- Gemeindeschlüssel z.B. '05766040' = Lage -- Achtung: hinten mit Leerzeichen aufgefüllt!! -- gemname character(100), -- Name -- "pp_gemarkung" ersetzen -- ---------------------------- -- "pp_gemarkung" ist eine optimierte Tabelle der Gemarkungen aus dem Post-Processing der Classic-Variante. -- In der NAV eErsetzen durch: -- TABLE gema_shl ( -- gemashl character(6) NOT NULL, -- Gemarkungsschlüssel z.B. '052005' = Lage -- gemarkung character(50), -- Name -- gemshl character(30), -- Gemeindeschlüssel z.B. '05766040' = Lage oder leer -- Achtung: hinten mit Leerzeichen aufgefüllt!! -- ag_shl character(4), -- ?? leer -- "pp_flur" ersetzen -- ------------------- -- "pp_flur" ist eine optimierte Tabelle der Katasterfluren aus dem Post-Processing der Classic-Variante. -- In der NAV eErsetzen durch: -- TABLE ax_gemarkungsteilflur ( -- gml_id character(16) NOT NULL, -- Identifikator, global eindeutig -- endet character(20), -- schluesselgesamt character varying, -- (DER) SCH[CharacterString] 'Schlüssel (gesamt)' LLGGGFFF Land-Gemerkung-Flur -- bezeichnung character varying, -- BEZ[CharacterString] 'Bezeichnung' FFF FLurnummer mit führenden Nullen -- land character varying, -- LAN[CharacterString] Bundesland. LL '05' -- gemarkung integer, -- GMN[CharacterString] Gemarkung. GGGG -- gemarkungsteilflur integer, -- FLR[CharacterString] Gemarkungsteil bzw. Flur. -- Tabelle "gemeinde_person" ersetzen -- ----------------------------------- -- -- I n d i c e s -- ============================ -- Tabelle "ax_gemarkungsteilflur" sollte Such-Index erhalten auf "gemarkung". -- Für Auflistung aller Fluren zur Gemarkung in Script "alkisnav_fls", Function "EineGemarkung". -- Der WMS "Flurstuecke_Kommunal" (aus View "st_flurst[gkz]") wird langsam, -- wenn er in einer kreisweiten Datenbank ausgeführt wird. -- Das Filter-Feld benötigt einen Index: DROP INDEX if exists ax_person_nname; CREATE INDEX ax_person_nname ON ax_person USING btree (nachnameoderfirma COLLATE pg_catalog."default"); -- V i e w s -- ============================ -- Bausteine für andere Views: -- --------------------------- -- Ein View, der die Verbindung von Flurstück zur Buchung für zwei verschiedene Fälle herstellt. -- Einmal die "normalen" (direkten) Buchungen. -- Zweitens über die Rechte von Buchungsstellen an anderen Buchungsstellen. -- Dies kann als "Mittelstück" in den anderen Views eingefügt werden. -- Einfach/Direkt: -- Flurstück >istGebucht> (Buchungs-Stelle) -- -- Mit "Recht an": -- Flurstück >istGebucht> Buchungs-Stelle istGebucht> Buchungstelle SELECT f1.gml_id AS fsgml, -- gml_id Flurstück b1.gml_id AS bsgml, -- gml_id Buchungs 0 AS ba_dien FROM ax_flurstueck f1 JOIN ax_buchungsstelle b1 ON f1.istgebucht = b1.gml_id UNION -- FS >istGebucht> Buchungstelle weistAuf> ax_lagebezeichnungMIThausnummer ax_lagebezeichnungkatalogeintrag SELECT fm.gml_id AS fsgml, sm.gml_id AS stgml, -- Filter: gml_id der Straße 'm' AS fall -- Sätze unterschieden: Mit HsNr FROM ax_flurstueck fm -- Flurstück Mit JOIN ax_lagebezeichnungmithausnummer lm -- Lage MIT ON lm.gml_id = ANY (fm.weistauf) JOIN ax_lagebezeichnungkatalogeintrag sm ON lm.land=sm.land AND lm.regierungsbezirk=sm.regierungsbezirk AND lm.kreis=sm.kreis AND lm.gemeinde=sm.gemeinde AND lm.lage=sm.lage WHERE lm.endet IS NULL AND fm.endet IS NULL -- nichts Historisches UNION -- Flurstück >zeigtAuf> ax_lagebezeichnungOHNEhausnummer ax_lagebezeichnungkatalogeintrag SELECT fo.gml_id AS fsgml, so.gml_id AS stgml, -- Filter: gml_id der Straße 'o' AS fall -- Sätze unterschieden: Ohne HsNr FROM ax_flurstueck fo -- Flurstück OHNE JOIN ax_lagebezeichnungohnehausnummer lo -- Lage OHNE ON lo.gml_id = ANY (fo.zeigtauf) JOIN ax_lagebezeichnungkatalogeintrag so -- Straße OHNE ON lo.land=so.land AND lo.regierungsbezirk=so.regierungsbezirk AND lo.kreis=so.kreis AND lo.gemeinde=so.gemeinde AND lo.lage=so.lage WHERE lo.endet IS NULL AND fo.endet IS NULL; -- nichts Historisches COMMENT ON VIEW public.flst_an_strasse IS 'ALKIS-Beziehung von Flurstück zu Straßentabelle. UNION-Zusammenfassung der Fälle MIT und OHNE Hausnummer.'; -- Muss man noch dafür sorgen, dass Flurstück nicht doppelt vorkommt? z.B. mit DISTINCT -- Oder müssen ggf. mehrfache FS im Programm übersprungen werden? -- Generelle Export-Struktur "Flurstück - Buchung - Grundbuch - Person" -- -------------------------------------------------------------------- -- Wird benötigt im Auskunft-Modul "alkisexport.php": -- Je nach aufrufendem Modul wird der Filter (WHERE) an anderer Stelle gesetzt (gml_id von FS, GB oder Pers.) -- Für Filter nach "Straße" siehe die nachfolgende Sonderversion "exp_csv_str". -- Problem / Konflikt: -- Es kann nur eine lineare Struktur aus Spalten und Zeilen exportiert werden. -- Wenn nicht nur die Daten des Ausgangs-Objektes exportiert werden, sondern auch verbundene Tabellen in -- einer 1:N-Struktur, dann verdoppeln sich Zeileninhalte und es werden redundante Daten erzeugt. -- Diese Redundanzen müssen vom dem Programm gefiltert werden, das die Daten über eine Schnittstelle einliest. -- Anwendungs-Beispiel: Abrechnung von Anliegerbeiträgen. /* DROP VIEW IF EXISTS exp_csv_alt; CREATE OR REPLACE VIEW exp_csv_alt AS SELECT -- F l u r s t ü c k f.gml_id AS fsgml, -- möglicher Filter Flurstücks-GML-ID f.flurstueckskennzeichen AS fs_kennz, f.gemarkungsnummer, -- Teile des FS-Kennz. noch mal einzeln f.flurnummer, f.zaehler, f.nenner, f.amtlicheflaeche AS fs_flae, g.bezeichnung AS gemarkung, -- G r u n d b u c h gb.gml_id AS gbgml, -- möglicher Filter Grundbuch-GML-ID gb.bezirk AS gb_bezirk, gb.buchungsblattnummermitbuchstabenerweiterung AS gb_blatt, z.bezeichnung AS beznam, -- GB-Bezirks-Name -- B u c h u n g s s t e l l e (Grundstück) s.laufendenummer AS bu_lfd, -- BVNR --s.zaehler, s.nenner, -- Anteil des GB am FS, einzelne Felder '=' || s.zaehler || '/' || s.nenner AS bu_ant, -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN über 'Recht an') s.buchungsart, -- verschlüsselt --b.bezeichner AS bu_art, -- Buchungsart entschlüsselt wb.v AS bu_art, -- Buchungsart entschlüsselt -- N a m e n s N u m m e r (Normalfall mit Person) nn.laufendenummernachdin1421 AS nam_lfd, '=' || nn.zaehler|| '/' || nn.nenner AS nam_ant, -- als Excel-Formel -- R e c h t s g e m e i n s c h a f t (Sonderfall von Namensnummer, ohne Person, ohne Nummer) -- Aus Subquery rg rg.artderrechtsgemeinschaft AS nam_adr, rg.v AS nam_adrv, -- Art der Rechtsgem. - Value zum Key rg.beschriebderrechtsgemeinschaft AS nam_bes, -- P e r s o n p.gml_id AS psgml, -- möglicher Filter Personen-GML-ID p.anrede, -- Anrede key wp.v AS anrv, -- Anrede Value zum Key p.vorname, p.namensbestandteil, p.nachnameoderfirma, -- Familienname p.geburtsdatum, --p.geburtsname, p.akademischergrad -- A d r e s s e der Person a.postleitzahlpostzustellung AS plz, a.ort_post AS ort, -- Anschreifenzeile 1: PLZ+Ort a.strasse, a.hausnummer, -- Anschriftenzeile 2: Straße+HsNr a.bestimmungsland AS land FROM ax_flurstueck f -- Flurstück JOIN doppelverbindung d -- beide Fälle über Union-View: direkt und über Recht von Buchung an Buchung ON d.fsgml = f.gml_id JOIN ax_gemarkung g -- entschlüsseln ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer JOIN ax_buchungsstelle s -- Buchungs-Stelle ON d.bsgml = s.gml_id JOIN ax_buchungsblatt gb -- Buchung >istBestandteilVon> Grundbuchblatt ON gb.gml_id = s.istbestandteilvon JOIN ax_buchungsblattbezirk z ON gb.land=z.land AND gb.bezirk=z.bezirk JOIN ax_namensnummer nn -- Blatt benennt> Person ON p.gml_id = nn.benennt LEFT JOIN ax_anschrift a ON a.gml_id = ANY (p.hat) -- E n t s c h l ü s s e l n: LEFT JOIN alkis_wertearten wp -- Entschlüsseln "Person - Anrede" ON cast(p.anrede AS character varying)=wp.k AND wp.element='ax_person' AND wp.bezeichnung='anrede' LEFT JOIN alkis_wertearten wb -- Entschlüsseln "Buchungsart" ON cast(s.buchungsart AS character varying) = wb.k AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' -- 2mal "LEFT JOIN" verdoppelt die Zeile in der Ausgabe. Darum als Subquery in Spalten packen: -- Noch mal "GB -> NamNum", aber dieses Mal für "Rechtsgemeinschaft". -- Kommt max. 1 mal je GB vor und hat keine Relation auf Person. LEFT JOIN ( SELECT gr.gml_id, r.artderrechtsgemeinschaft, r.beschriebderrechtsgemeinschaft, wr.v FROM ax_namensnummer r JOIN ax_buchungsblatt gr ON r.istbestandteilvon = gr.gml_id -- Blatt istGebucht> Buchungstelle ON f.istgebucht = s.gml_id JOIN ax_buchungsblatt gb -- Buchung >istBestandteilVon> Grundbuchblatt ON gb.gml_id = s.istbestandteilvon JOIN ax_buchungsblattbezirk z ON gb.land=z.land AND gb.bezirk=z.bezirk JOIN ax_namensnummer nn -- Blatt benennt> Person ON p.gml_id = nn.benennt LEFT JOIN ax_anschrift a ON a.gml_id = ANY (p.hat) -- E n t s c h l ü s s e l n: LEFT JOIN alkis_wertearten wp -- Entschlüsseln "Person - Anrede" ON cast(p.anrede AS character varying) = wp.k AND wp.element = 'ax_person' AND wp.bezeichnung = 'anrede' LEFT JOIN alkis_wertearten wb -- Entschlüsseln "Buchungsart" ON cast(s.buchungsart AS character varying) = wb.k -- buchungsart = integer / .k = char 4stellig AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' -- 2mal "LEFT JOIN" verdoppelt die Zeile in der Ausgabe. Darum als Subquery in Spalten packen: -- Noch mal "GB -> NamNum", aber dieses Mal für "Rechtsgemeinschaft". -- Kommt max. 1 mal je GB vor und hat keine Relation auf Person. LEFT JOIN ( SELECT gr.gml_id, r.artderrechtsgemeinschaft, r.beschriebderrechtsgemeinschaft, wr.v FROM ax_namensnummer r JOIN ax_buchungsblatt gr ON r.istbestandteilvon = gr.gml_id -- Blatt istGebucht> Buchungstelle istBestandteilVon> Grundbuchblatt ON gb.gml_id = s.istbestandteilvon JOIN ax_buchungsblattbezirk z ON gb.land=z.land AND gb.bezirk=z.bezirk JOIN ax_namensnummer nn -- Blatt benennt> Person ON p.gml_id = nn.benennt LEFT JOIN ax_anschrift a ON a.gml_id = ANY (p.hat) -- E n t s c h l ü s s e l n: LEFT JOIN alkis_wertearten wp -- Entschlüsseln "Person - Anrede" ON cast(p.anrede AS character varying)=wp.k AND wp.element='ax_person' AND wp.bezeichnung='anrede' LEFT JOIN alkis_wertearten wb -- Entschlüsseln "Buchungsart" ON cast(s.buchungsart AS character varying) = wb.k AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' LEFT JOIN ( SELECT gr.gml_id, r.artderrechtsgemeinschaft, r.beschriebderrechtsgemeinschaft, wr.v FROM ax_namensnummer r JOIN ax_buchungsblatt gr ON r.istbestandteilvon = gr.gml_id -- Blatt istBestandteilVon> Grundbuchblatt ON gb.gml_id = s.istbestandteilvon JOIN ax_buchungsblattbezirk z ON gb.land=z.land AND gb.bezirk=z.bezirk JOIN ax_namensnummer nn -- Blatt benennt> Person ON p.gml_id = nn.benennt LEFT JOIN ax_anschrift a ON a.gml_id = ANY (p.hat) -- E n t s c h l ü s s e l n: LEFT JOIN alkis_wertearten wp -- Entschlüsseln "Person - Anrede" ON cast(p.anrede AS character varying)=wp.k AND wp.element='ax_person' AND wp.bezeichnung='anrede' LEFT JOIN alkis_wertearten wb -- Entschlüsseln "Buchungsart" ON cast(s.buchungsart AS character varying)=wb.k AND wp.element='ax_buchungsstelle' AND wp.bezeichnung='buchungsart' -- 2mal "LEFT JOIN" verdoppelt die Zeile in der Ausgabe. Darum als Subquery in Spalten packen: -- Noch mal "GB -> NamNum", aber dieses Mal für "Rechtsgemeinschaft". -- Kommt max. 1 mal je GB vor und hat keine Relation auf Person. LEFT JOIN ( SELECT gr.gml_id, r.artderrechtsgemeinschaft, r.beschriebderrechtsgemeinschaft, wr.v FROM ax_namensnummer r JOIN ax_buchungsblatt gr ON r.istbestandteilvon = gr.gml_id -- Blatt istGebucht> Buchungstelle ON f.istgebucht = s.gml_id JOIN ax_buchungsblatt gb -- Buchung >istBestandteilVon> Grundbuchblatt ON gb.gml_id = s.istbestandteilvon JOIN ax_buchungsblattbezirk z ON gb.land=z.land AND gb.bezirk=z.bezirk JOIN ax_namensnummer nn -- Blatt benennt> Person ON p.gml_id = nn.benennt LEFT JOIN ax_anschrift a ON a.gml_id = ANY (p.hat) -- E n t s c h l ü s s e l n: LEFT JOIN alkis_wertearten wp -- Entschlüsseln "Person - Anrede" ON cast(p.anrede AS character varying) = wp.k AND wp.element = 'ax_person' AND wp.bezeichnung = 'anrede' LEFT JOIN alkis_wertearten wb -- Entschlüsseln "Buchungsart" ON cast(s.buchungsart AS character varying) = wb.k -- buchungsart = integer / .k = char 4stellig AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' -- 2mal "LEFT JOIN" verdoppelt die Zeile in der Ausgabe. Darum als Subquery in Spalten packen: -- Noch mal "GB -> NamNum", aber dieses Mal für "Rechtsgemeinschaft". -- Kommt max. 1 mal je GB vor und hat keine Relation auf Person. LEFT JOIN ( SELECT gr.gml_id, r.artderrechtsgemeinschaft, r.beschriebderrechtsgemeinschaft, wr.v FROM ax_namensnummer r JOIN ax_buchungsblatt gr ON r.istbestandteilvon = gr.gml_id -- Blatt istGebucht> Buchungstelle istBestandteilVon> Grundbuchblatt ON gb.gml_id = s.istbestandteilvon JOIN ax_buchungsblattbezirk z ON gb.land=z.land AND gb.bezirk=z.bezirk JOIN ax_namensnummer nn -- Blatt benennt> Person ON p.gml_id = nn.benennt LEFT JOIN ax_anschrift a ON a.gml_id = ANY (p.hat) -- E n t s c h l ü s s e l n: LEFT JOIN alkis_wertearten wp -- Entschlüsseln "Person - Anrede" ON cast(p.anrede AS character varying)=wp.k AND wp.element='ax_person' AND wp.bezeichnung='anrede' LEFT JOIN alkis_wertearten wb -- Entschlüsseln "Buchungsart" ON cast(s.buchungsart AS character varying) = wb.k AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' LEFT JOIN ( SELECT gr.gml_id, r.artderrechtsgemeinschaft, r.beschriebderrechtsgemeinschaft, wr.v FROM ax_namensnummer r JOIN ax_buchungsblatt gr ON r.istbestandteilvon = gr.gml_id -- Blatt