Index: trunk/import/norgis_alkis_pp/postcreate.d/views_exp_csv.sql
===================================================================
--- trunk/import/norgis_alkis_pp/postcreate.d/views_exp_csv.sql	(revision 401)
+++ trunk/import/norgis_alkis_pp/postcreate.d/views_exp_csv.sql	(revision 401)
@@ -0,0 +1,629 @@
+
+-- ===================================================================================
+--  ALKIS-PostGIS   Mapbender-Navigation und Buchauskunft fÃŒr NorGIS-ALKIS-Importer
+-- ===================================================================================
+
+-- Aufgabe:       Views bereit stellen fÃŒr den CSV-Export in der ALKIS-Buch-Auskunft.
+-- AusfÃŒhrung in: Step "postcreate.d" des ALKIS-Importers. Hier also nur Definitionen machen, keine Daten bearbeiten.
+
+--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)
+--  2017-02-23 Spalte "fall" aus View "flst_an_strasse" im View "exp_csv_str" ausgeben.
+--             Darauf basiert ein neuer Filter im Programm "alkisexport.php".
+--			Sortierung FS-Kennz. repariert in Views "exp_csv" und "exp_csv_str"
+--  2017-10-10 Berechtigungen rausgenommen in getrennte Datei
+--  2017-12-06 Umbenennung von "x_classic2norgis.sql" nach "views_exp_csv.sql"
+--  2017-12-20 Beseitigung des Fehlers: Mehrere Adressen zur Person fuehren zu mehrfachen Zeilen (Wiederholung FlurstÃŒck und Flaeche ..)
+--             Es wird je Persoon nur noch die "letzte" Adresse verwendet (subquery).
+--             Der View "exp_csv_str" ist jetzt direkt als 4fach-UNION (2x2) codiert statt mit eingebettetem gespeicherten 2fach-Union.
+--             Hauptvorteil: Keine undurchsichtigen AbhÃ€ngigkeiten. Ist auch etwas schneller.
+--  2017-12-20 Suche (Sortierung) 'letzte Adresse' nach "beginnt" statt nach "gml_id"
+
+-- ToDo:
+--  - die alten Ãbersichten "pp_flur", "pp_gemarkung" und "pp_gemeinde" wieder erzeugen
+--    Siehe Script: "pp_gebiete.sql" (FÃŒllen) und Teile von "pp_definition.sql" (DB-Struktur).
+
+
+-- 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][e|r]") 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 StraÃentabelle fÃŒr zwei verschiedene FÃ€lle herstellt.
+-- Einmal ÃŒber die Lagebezeichnung MIT Hausnummer und einmal OHNE.
+-- Dies kann als "MittelstÃŒck" in den anderen Views eingefÃŒgt werden.
+
+   DROP VIEW if exists public.flst_an_strasse CASCADE; -- wird nicht mehr verwendet
+/*
+CREATE OR REPLACE VIEW public.flst_an_strasse
+AS
+  -- FlurstÃŒck >weistAuf> ax_lagebezeichnungMIThausnummer <JOIN> 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 <JOIN> 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.';
+*/
+
+
+-- 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;
+CREATE OR REPLACE VIEW exp_csv
+AS
+ SELECT -- Fall: einfache Buchung (ohne "Recht an")
+  -- 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  AS bu_ant,      -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN ÃŒber 'Recht an')
+    s.buchungsart,                                       -- verschlÃŒ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)
+    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,
+  -- 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 ax_gemarkung g                   -- entschlÃŒsseln
+    ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer 
+  JOIN ax_buchungsstelle s              -- FS >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 <istBestandteilVon< NamNum
+    ON gb.gml_id = nn.istbestandteilvon
+  JOIN ax_person p                      -- NamNum >benennt> Person 
+    ON p.gml_id = nn.benennt
+  LEFT JOIN ax_anschrift a              -- nur die "letzte" Anschrift zur Person verwenden
+    ON a.gml_id = (SELECT gml_id FROM ax_anschrift an WHERE an.gml_id = ANY(p.hat) AND an.endet IS NULL ORDER BY an.beginnt DESC LIMIT 1)
+  -- 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 <istBestandteilVon< NamNum (Rechtsgemeinschaft) 
+      LEFT JOIN alkis_wertearten wr
+        ON cast(r.artderrechtsgemeinschaft AS character varying)=wr.k AND wr.element='ax_namensnummer' AND wr.bezeichnung='artderrechtsgemeinschaft' 
+      WHERE NOT r.artderrechtsgemeinschaft IS NULL ) AS rg -- Rechtsgemeinschaft
+   ON rg.gml_id = gb.gml_id  -- zum GB
+  WHERE f.endet IS NULL AND s.endet IS NULL and gb.endet IS NULL and nn.endet IS NULL AND p.endet IS NULL
+---------
+  UNION
+---------
+ SELECT  -- Fall: "Recht an"
+  -- 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  AS bu_ant,      -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN ÃŒber 'Recht an')
+    s.buchungsart,                                       -- verschlÃŒ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)
+    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,
+  -- 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 ax_gemarkung g                   -- entschlÃŒsseln
+    ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer 
+  -- FS >istGebucht> Buchungstelle  <an<  Buchungstelle
+ -- Variante mit 2 Buchungs-Stellen (Recht An)
+  JOIN ax_buchungsstelle dien           -- dienende Buchung
+    ON f.istgebucht = dien.gml_id
+  JOIN ax_buchungsstelle s              -- herrschende Buchung
+    ON dien.gml_id = ANY (s.an)         -- hat Recht an
+  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 <istBestandteilVon< NamNum
+    ON gb.gml_id = nn.istbestandteilvon
+  JOIN ax_person p                      -- NamNum >benennt> Person 
+    ON p.gml_id = nn.benennt
+  LEFT JOIN ax_anschrift a               -- nur die "letzte" Anschrift zur Person verwenden
+    ON a.gml_id = (SELECT gml_id FROM ax_anschrift an WHERE an.gml_id = ANY(p.hat) AND an.endet IS NULL ORDER BY an.beginnt DESC LIMIT 1)
+  -- 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< NamNum (Rechtsgemeinschaft) 
+      LEFT JOIN alkis_wertearten wr
+        ON cast(r.artderrechtsgemeinschaft AS character varying)=wr.k AND wr.element='ax_namensnummer' AND wr.bezeichnung='artderrechtsgemeinschaft' 
+      WHERE NOT r.artderrechtsgemeinschaft IS NULL ) AS rg -- Rechtsgemeinschaft
+   ON rg.gml_id = gb.gml_id  -- zum GB
+  WHERE f.endet IS NULL AND s.endet IS NULL and gb.endet IS NULL and nn.endet IS NULL AND p.endet IS NULL
+    AND dien.endet IS NULL
+
+ORDER BY fs_kennz,   -- f.flurstueckskennzeichen, 
+      -- fsgml,      
+         gb_bezirk,  -- gb.bezirk, 
+         gb_blatt,   -- gb.buchungsblattnummermitbuchstabenerweiterung,
+         bu_lfd,     -- s.laufendenummer,
+         nam_lfd;    -- nn.laufendenummernachdin1421
+
+COMMENT ON VIEW exp_csv 
+ IS 'View fÃŒr einen CSV-Export aus der Buchauskunft mit alkisexport.php. Generelle Struktur. FÃŒr eine bestimmte gml_id noch den Filter setzen.';
+
+
+-- Eine Variante des View "exp_csv":
+-- Hier wird zusÃ€tzlich die Lagebezeichnung zum FlurstÃŒck angebunden in den Varianten MIT/OHNE Hausnummer.
+-- Der Filter "WHERE stgml= " auf die "gml_id" von "ax_lagebezeichnungkatalogeintrag" sollte gesetzt werden,
+-- um nur die FlurstÃŒcke zu bekommen, die an einer StraÃe liegen.
+
+DROP VIEW IF EXISTS exp_csv_str;
+
+CREATE OR REPLACE VIEW exp_csv_str
+AS      -- Version mit 4fach-UNION (2x2 FÃ€lle) statt eingebauter View "flst_an_strasse"
+ SELECT -- Fall 1: einfache Buchung (ohne Recht an)  // Lagebezeichnung MIT Hausnummer
+    sm.gml_id                            AS stgml,       -- Filter: gml_id der StraÃe aus "ax_lagebezeichnungkatalogeintrag"
+    'm'                                  AS fall,        -- SÃ€tze unterschieden: MIT HsNr
+  -- 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  AS bu_ant,      -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN ÃŒber 'Recht an')
+    s.buchungsart,                                       -- verschlÃŒ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)
+    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,
+  -- A d r e s s e  der Person
+    a.postleitzahlpostzustellung         AS plz,
+    a.ort_post                           AS ort,         -- Anschriftenzeile 1: PLZ+Ort
+    a.strasse,  a.hausnummer,                            -- Anschriftenzeile 2: StraÃe+HsNr
+    a.bestimmungsland                    AS land
+  FROM ax_flurstueck    f               -- FlurstÃŒck
+  -- FlurstÃŒck >weistAuf> ax_lagebezeichnungMIThausnummer <JOIN> ax_lagebezeichnungkatalogeintrag
+  JOIN ax_lagebezeichnungmithausnummer lm -- Lage MIT
+    ON lm.gml_id = ANY (f.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 
+   JOIN ax_gemarkung g                   -- entschlÃŒsseln
+    ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer 
+  JOIN ax_buchungsstelle s              -- FS >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 <istBestandteilVon< NamNum
+    ON gb.gml_id = nn.istbestandteilvon
+  JOIN ax_person p                      -- NamNum >benennt> Person 
+    ON p.gml_id = nn.benennt
+  LEFT JOIN ax_anschrift a              -- nur die "letzte" Anschrift zur Person verwenden
+    ON a.gml_id = (SELECT gml_id FROM ax_anschrift an WHERE an.gml_id = ANY(p.hat) AND an.endet IS NULL ORDER BY an.beginnt DESC LIMIT 1)
+  -- 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 <istBestandteilVon< NamNum (Rechtsgemeinschaft) 
+      LEFT JOIN alkis_wertearten wr
+        ON cast(r.artderrechtsgemeinschaft AS character varying)=wr.k AND wr.element='ax_namensnummer' AND wr.bezeichnung='artderrechtsgemeinschaft' 
+      WHERE NOT r.artderrechtsgemeinschaft IS NULL ) AS rg -- Rechtsgemeinschaft
+   ON rg.gml_id = gb.gml_id  -- zum GB
+  WHERE f.endet IS NULL AND s.endet IS NULL and gb.endet IS NULL and nn.endet IS NULL AND p.endet IS NULL AND lm.endet IS NULL  
+---------
+  UNION
+---------
+ SELECT -- Fall 2: 2 Buchungs-Stellen (Recht An)  //  Lagebezeichnung MIT Hausnummer
+    sm.gml_id                            AS stgml,       -- Filter: gml_id der StraÃe aus "ax_lagebezeichnungkatalogeintrag"
+    'm'                                  AS fall,        -- SÃ€tze unterschieden: MIT HsNr
+  -- 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  AS bu_ant,      -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN ÃŒber 'Recht an')
+    s.buchungsart,                                       -- verschlÃŒ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)
+    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,
+   -- A d r e s s e  der Person
+    a.postleitzahlpostzustellung         AS plz,
+    a.ort_post                           AS ort,         -- Anschriftenzeile 1: PLZ+Ort
+    a.strasse,  a.hausnummer,                            -- Anschriftenzeile 2: StraÃe+HsNr
+    a.bestimmungsland                    AS land
+  FROM ax_flurstueck f                  -- FlurstÃŒck
+  -- FlurstÃŒck >weistAuf> ax_lagebezeichnungMIThausnummer <JOIN> ax_lagebezeichnungkatalogeintrag
+  JOIN ax_lagebezeichnungmithausnummer lm  -- Lage MIT
+    ON lm.gml_id = ANY (f.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 
+  JOIN ax_gemarkung g                   -- entschlÃŒsseln
+    ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer 
+  -- FS >istGebucht> Buchungstelle  <an<  Buchungstelle
+ -- Variante mit 2 Buchungs-Stellen (Recht An)
+  JOIN ax_buchungsstelle dien           -- dienende Buchung
+    ON f.istgebucht = dien.gml_id
+  JOIN ax_buchungsstelle s              -- herrschende Buchung
+    ON dien.gml_id = ANY (s.an)         -- hat Recht an
+  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 <istBestandteilVon< NamNum
+    ON gb.gml_id = nn.istbestandteilvon
+  JOIN ax_person p                      -- NamNum >benennt> Person 
+    ON p.gml_id = nn.benennt
+  LEFT JOIN ax_anschrift a              -- nur die "letzte" Anschrift zur Person verwenden
+    ON a.gml_id = (SELECT gml_id FROM ax_anschrift an WHERE an.gml_id = ANY(p.hat) AND an.endet IS NULL ORDER BY an.beginnt DESC LIMIT 1)
+  -- 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< NamNum (Rechtsgemeinschaft) 
+      LEFT JOIN alkis_wertearten wr
+        ON cast(r.artderrechtsgemeinschaft AS character varying)=wr.k AND wr.element='ax_namensnummer' AND wr.bezeichnung='artderrechtsgemeinschaft' 
+      WHERE NOT r.artderrechtsgemeinschaft IS NULL ) AS rg -- Rechtsgemeinschaft
+   ON rg.gml_id = gb.gml_id  -- zum GB
+  WHERE f.endet IS NULL AND s.endet IS NULL and gb.endet IS NULL and nn.endet IS NULL AND p.endet IS NULL
+    AND dien.endet IS NULL AND lm.endet IS NULL  
+---------
+  UNION
+---------
+ SELECT -- Fall 3: einfache Buchung (ohne Recht an)  //  Lagebezeichnung OHNE Hausnummer
+    so.gml_id                            AS stgml,       -- Filter: gml_id der StraÃe aus "ax_lagebezeichnungkatalogeintrag"
+    'o'                                  AS fall,        -- SÃ€tze unterschieden: OHNE HsNr
+  -- 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  AS bu_ant,      -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN ÃŒber 'Recht an')
+    s.buchungsart,                                       -- verschlÃŒ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)
+    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,
+  -- A d r e s s e  der Person
+    a.postleitzahlpostzustellung         AS plz,
+    a.ort_post                           AS ort,         -- Anschriftenzeile 1: PLZ+Ort
+    a.strasse,  a.hausnummer,                            -- Anschriftenzeile 2: StraÃe+HsNr
+    a.bestimmungsland                    AS land
+  FROM ax_flurstueck    f               -- FlurstÃŒck
+-- FlurstÃŒck >zeigtAuf> ax_lagebezeichnungOHNEhausnummer <JOIN> ax_lagebezeichnungkatalogeintrag
+  JOIN ax_lagebezeichnungohnehausnummer lo -- Lage OHNE
+    ON lo.gml_id = ANY (f.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
+  JOIN ax_gemarkung g                   -- entschlÃŒsseln
+    ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer 
+  JOIN ax_buchungsstelle s              -- FS >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 <istBestandteilVon< NamNum
+    ON gb.gml_id = nn.istbestandteilvon
+  JOIN ax_person p                      -- NamNum >benennt> Person 
+    ON p.gml_id = nn.benennt
+  LEFT JOIN ax_anschrift a              -- nur die "letzte" Anschrift zur Person verwenden
+    ON a.gml_id = (SELECT gml_id FROM ax_anschrift an WHERE an.gml_id = ANY(p.hat) AND an.endet IS NULL ORDER BY an.beginnt DESC LIMIT 1)
+  -- 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 <istBestandteilVon< NamNum (Rechtsgemeinschaft) 
+      LEFT JOIN alkis_wertearten wr
+        ON cast(r.artderrechtsgemeinschaft AS character varying)=wr.k AND wr.element='ax_namensnummer' AND wr.bezeichnung='artderrechtsgemeinschaft' 
+      WHERE NOT r.artderrechtsgemeinschaft IS NULL ) AS rg -- Rechtsgemeinschaft
+   ON rg.gml_id = gb.gml_id  -- zum GB
+  WHERE f.endet IS NULL AND s.endet IS NULL and gb.endet IS NULL and nn.endet IS NULL AND p.endet IS NULL AND lo.endet IS NULL 
+---------
+  UNION
+---------
+ SELECT -- Fall 4: 2 Buchungs-Stellen (Recht An)  //  Lagebezeichnung OHNE Hausnummer
+    so.gml_id                            AS stgml,       -- Filter: gml_id der StraÃe aus "ax_lagebezeichnungkatalogeintrag"
+    'o'                                  AS fall,        -- SÃ€tze unterschieden: OHNE HsNr
+  -- 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  AS bu_ant,      -- als Excel-Formel (nur bei Wohnungsgrundbuch JOIN ÃŒber 'Recht an')
+    s.buchungsart,                                       -- verschlÃŒ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)
+    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,
+   -- A d r e s s e  der Person
+    a.postleitzahlpostzustellung         AS plz,
+    a.ort_post                           AS ort,         -- Anschriftenzeile 1: PLZ+Ort
+    a.strasse,  a.hausnummer,                            -- Anschriftenzeile 2: StraÃe+HsNr
+    a.bestimmungsland                    AS land
+  FROM ax_flurstueck f                  -- FlurstÃŒck
+-- FlurstÃŒck >zeigtAuf> ax_lagebezeichnungOHNEhausnummer <JOIN> ax_lagebezeichnungkatalogeintrag
+  JOIN ax_lagebezeichnungohnehausnummer lo -- Lage OHNE
+    ON lo.gml_id = ANY (f.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
+  JOIN ax_gemarkung g                   -- entschlÃŒsseln
+    ON f.land=g.land AND f.gemarkungsnummer=g.gemarkungsnummer 
+  -- FS >istGebucht> Buchungstelle  <an<  Buchungstelle
+ -- Variante mit 2 Buchungs-Stellen (Recht An)
+  JOIN ax_buchungsstelle dien           -- dienende Buchung
+    ON f.istgebucht = dien.gml_id
+  JOIN ax_buchungsstelle s              -- herrschende Buchung
+    ON dien.gml_id = ANY (s.an)         -- hat Recht an
+  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 <istBestandteilVon< NamNum
+    ON gb.gml_id = nn.istbestandteilvon
+  JOIN ax_person p                      -- NamNum >benennt> Person 
+    ON p.gml_id = nn.benennt
+  LEFT JOIN ax_anschrift a              -- nur die "letzte" Anschrift zur Person verwenden
+    ON a.gml_id = (SELECT gml_id FROM ax_anschrift an WHERE an.gml_id = ANY(p.hat) AND an.endet IS NULL ORDER BY an.beginnt DESC LIMIT 1)
+  -- 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< NamNum (Rechtsgemeinschaft) 
+      LEFT JOIN alkis_wertearten wr
+        ON cast(r.artderrechtsgemeinschaft AS character varying)=wr.k AND wr.element='ax_namensnummer' AND wr.bezeichnung='artderrechtsgemeinschaft' 
+      WHERE NOT r.artderrechtsgemeinschaft IS NULL ) AS rg -- Rechtsgemeinschaft
+   ON rg.gml_id = gb.gml_id  -- zum GB
+  WHERE f.endet IS NULL AND s.endet IS NULL and gb.endet IS NULL and nn.endet IS NULL AND p.endet IS NULL
+    AND dien.endet IS NULL AND lo.endet IS NULL 
+
+ORDER BY fs_kennz,   -- f.flurstueckskennzeichen, 
+         gb_bezirk,  -- gb.bezirk, 
+         gb_blatt,   -- gb.buchungsblattnummermitbuchstabenerweiterung,
+         bu_lfd,     -- s.laufendenummer,
+         nam_lfd;    -- nn.laufendenummernachdin1421
+
+COMMENT ON VIEW exp_csv_str 
+ IS 'View fÃŒr einen CSV-Export aus der Buchauskunft mit alkisexport.php. Liefert nur FlurstÃŒcke, die eine Lagebezeichnung MIT/OHNE Hausnummer haben. Dazu noch den Filter auf GML-ID der StraÃentabelle setzen.';
+
+
+-- Berechtigung
+-- ============
+  GRANT SELECT ON TABLE public.exp_csv          TO mb27;
+  GRANT SELECT ON TABLE public.exp_csv_str      TO mb27;
+
+-- Ende --
Index: trunk/import/norgis_alkis_pp/postcreate.d/views_buchungsketten.sql
===================================================================
--- trunk/import/norgis_alkis_pp/postcreate.d/views_buchungsketten.sql	(revision 401)
+++ trunk/import/norgis_alkis_pp/postcreate.d/views_buchungsketten.sql	(revision 401)
@@ -0,0 +1,298 @@
+
+-- ====================================================================================================
+--  ALKIS-PostGIS  FlurstÃŒcke Suchen, die eine Verkettung von mehreren Buchungsstellen haben
+-- ====================================================================================================
+
+-- Aufgaben:
+-- ---------
+-- FlurstÃŒcke ermitteln die 2 bis 4 (oder mehr?) Buchungsstellen haben die jeweils ein "Recht an" einer anderen Buchungsstelle haben.
+-- Beispiel:
+--   "Wohnungs-/Teiluntererbbaurecht" >an> "Aufgeteiltes Untererbbaurecht WEG" >an> "Erbbaurecht" >an> "GrundstÃŒck" >Buchung> FlurstÃŒck 
+-- In einem WMS diese besonderen Buchungen hervorheben.
+-- Die betroffenen Buchungsarten auflisten.
+-- Auch einige EinzelfÃ€lle selektieren.
+-- Dies dient zunÃ€chst dazu, um TestfÃ€lle fÃŒr die Weiterentwicklung der Buchauskunft zu finden (Entwicklung).
+-- Vielleicht hat auch ein Anwender Verwendung dafÃŒr.
+
+-- AusfÃŒhrung in:
+-- Step "postcreate.d" des ALKIS-Importers. Hier also nur Definitionen machen, keine Daten bearbeiten.
+
+--Stand 
+--  2017-12-07 Prototyp
+
+-- V i e w s
+-- =================================
+
+-- Views fÃŒr die Darstellung im WMS
+-- =================================
+
+-- 2 beteiligte Buchungsstellen
+-- "Erbbaurecht" und Ã€hnliches
+-- --------------------------
+-- FS >istGebucht> Buchungstelle 1  <an<  Buchungstelle 2
+-- --------------------------------------------------------------------
+   DROP VIEW IF EXISTS buchungsrechte_2arten;
+   DROP VIEW IF EXISTS buchungsrechte_2wms;
+CREATE OR REPLACE VIEW buchungsrechte_2wms
+AS
+ SELECT DISTINCT                    -- Ohne DISTINCT maherfache Ãberlagerung
+    f.gml_id,                       -- Unique Key
+    s2.buchungsart,                 -- verschlÃŒsselt (Nummer)
+    f.wkb_geometry
+ --, wb.v      AS bu_art            -- Buchungsart entschlÃŒsselt  -- Hier nicht!
+  FROM ax_flurstueck     f          -- FlurstÃŒck
+  JOIN ax_buchungsstelle s1         -- dienende Buchung
+    ON f.istgebucht = s1.gml_id
+  JOIN ax_buchungsstelle s2         -- herrschende Buchung
+    ON s1.gml_id = ANY(s2.an)       -- hat Recht an
+--JOIN alkis_wertearten wb          -- EntschlÃŒsseln "Buchungsart"
+--  ON cast(s2.buchungsart AS character varying) = wb.k 
+-- AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' 
+  WHERE f.endet IS NULL AND s1.endet IS NULL AND s2.endet IS NULL;
+
+COMMENT ON VIEW buchungsrechte_2wms IS 'FÃŒr WMS-Anzeige von FlurstÃŒcken mit Buchungsarten mit 2 beteiligten Buchungsstellen, z.B. Erbbaurecht.';
+GRANT SELECT ON TABLE public.buchungsrechte_2wms  TO ms6;
+
+
+-- 3 beteiligte Buchungsstellen
+-- "Untererbbaurecht" und Ã€hnliches
+-- --------------------------------
+-- FS >istGebucht> Buchungstelle 1  <an<  Buchungstelle 2 <an<  Buchungstelle 3
+-- ------------------------------------------------------------------------------------------------------------------
+   DROP VIEW IF EXISTS buchungsrechte_3arten;
+   DROP VIEW IF EXISTS buchungsrechte_3wms;
+CREATE OR REPLACE VIEW buchungsrechte_3wms
+AS
+ SELECT DISTINCT f.gml_id, s3.buchungsart, f.wkb_geometry
+   FROM ax_flurstueck     f  
+   JOIN ax_buchungsstelle s1 ON f.istgebucht = s1.gml_id
+   JOIN ax_buchungsstelle s2 ON s1.gml_id = ANY(s2.an)    
+   JOIN ax_buchungsstelle s3 ON s2.gml_id = ANY(s3.an)  
+  WHERE f.endet IS NULL AND s1.endet IS NULL AND s2.endet IS NULL AND s3.endet IS NULL;
+
+COMMENT ON VIEW buchungsrechte_3wms IS 'FÃŒr WMS-Anzeige von FlurstÃŒcken mit Buchungsarten mit 3 beteiligten Buchungsstellen, z.B. Untererbbaurecht.';
+GRANT SELECT ON TABLE public.buchungsrechte_3wms  TO ms6;
+-- z.B. 69 FlurstÃŒcke in Lage in 312 msec.
+
+
+-- 4 beteiligte Buchungsstellen
+-- Teil-Untererbbaurecht
+-- --------------------------------
+-- FS >istGebucht> Buchungstelle 1  <an<  Buchungstelle 2 <an<  Buchungstelle 3 <an<  Buchungstelle 4
+-- ------------------------------------------------------------------------------------------------------------------
+   DROP VIEW IF EXISTS buchungsrechte_4arten;
+   DROP VIEW IF EXISTS buchungsrechte_4wms;
+CREATE OR REPLACE VIEW buchungsrechte_4wms
+AS
+ SELECT DISTINCT f.gml_id, s4.buchungsart, f.wkb_geometry
+  FROM ax_flurstueck     f  
+  JOIN ax_buchungsstelle s1 ON f.istgebucht = s1.gml_id
+  JOIN ax_buchungsstelle s2 ON s1.gml_id = ANY(s2.an)    
+  JOIN ax_buchungsstelle s3 ON s2.gml_id = ANY(s3.an) 
+  JOIN ax_buchungsstelle s4 ON s3.gml_id = ANY(s4.an)  
+ WHERE f.endet IS NULL AND s1.endet IS NULL AND s2.endet IS NULL AND s3.endet IS NULL AND s4.endet IS NULL;
+
+COMMENT ON VIEW buchungsrechte_4wms IS 'FÃŒr WMS-Anzeige von FlurstÃŒcken mit Buchungsarten mit 4 beteiligten Buchungsstellen.';
+GRANT SELECT ON TABLE public.buchungsrechte_4wms  TO ms6;
+-- 6 FlurstÃŒcke im Kreis Minden-LÃŒbbecke,
+-- 3 FlurstÃŒcke in Lage in 180 msec. ("DENW17AL0000VffJ" "DENW17AL0000VnuJ" "DENW17AL0000Vwe1")
+
+
+-- Gibts das?  Nein!
+-- --------------------------------
+-- FS >istGebucht> Buchungstelle 1  <an<  Buchungstelle 2 <an<  Buchungstelle 3 <an<  Buchungstelle 4 <an<  Buchungstelle 5
+-- ------------------------------------------------------------------------------------------------------------------
+-- 5 beteiligte Buchungsstellen
+-- DROP VIEW IF EXISTS buchungsrechte_5wms;
+/*
+CREATE OR REPLACE VIEW buchungsrechte_5wms
+AS
+ SELECT DISTINCT f.gml_id, s5.buchungsart, f.wkb_geometry
+   FROM ax_flurstueck     f  
+   JOIN ax_buchungsstelle s1  ON f.istgebucht = s1.gml_id
+   JOIN ax_buchungsstelle s2  ON s1.gml_id = ANY (s2.an)    
+   JOIN ax_buchungsstelle s3  ON s2.gml_id = ANY (s3.an) 
+   JOIN ax_buchungsstelle s4  ON s3.gml_id = ANY (s4.an)  
+   JOIN ax_buchungsstelle s5  ON s4.gml_id = ANY (s5.an)  
+  WHERE f.endet IS NULL AND s1.endet IS NULL AND s2.endet IS NULL AND s3.endet IS NULL AND s4.endet IS NULL AND s5.endet IS NULL;
+
+COMMENT ON VIEW buchungsrechte_5wms IS 'FÃŒr WMS-Anzeige von FlurstÃŒcken mit Buchungsarten mit 5 beteiligten Buchungsstellen.';
+GRANT SELECT ON TABLE public.buchungsrechte_5wms  TO ms6;
+*/
+
+-- Views fÃŒr die Modellierung der Classes im WMS
+-- =============================================
+-- Buchungsart entschlÃŒsseln. Die Treffer der WMS-Views weiter verdichten:
+
+CREATE OR REPLACE VIEW buchungsrechte_2arten AS
+ SELECT DISTINCT s.buchungsart, wb.v AS bu_art
+   FROM buchungsrechte_2wms s
+   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' 
+  ORDER BY s.buchungsart; 
+COMMENT ON VIEW buchungsrechte_2arten IS 'Vorkommende Buchungsarten bei der Verkettung von 2 Buchungsstellen.';
+-- 1301;"Wohnungs-/Teileigentum"
+-- 1302;"Miteigentum Par. 3 Abs. 4 GBO"
+-- 2101;"Erbbaurecht"
+-- 2201;"Aufgeteiltes Erbbaurecht WEG"
+
+CREATE OR REPLACE VIEW buchungsrechte_3arten AS
+ SELECT DISTINCT s.buchungsart, wb.v AS bu_art
+   FROM buchungsrechte_3wms s
+   JOIN alkis_wertearten wb
+     ON cast(s.buchungsart AS character varying) = wb.k 
+    AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' 
+  ORDER BY buchungsart; 
+COMMENT ON VIEW buchungsrechte_3arten IS 'Vorkommende Buchungsarten bei der Verkettung von 3 Buchungsstellen.';
+-- 2102;"Untererbbaurecht"
+-- 2202;"Aufgeteiltes Untererbbaurecht WEG"
+-- 2203;"Aufgeteiltes Recht Par. 3 Abs. 4 GBO"
+-- 2301;"Wohnungs-/Teilerbbaurecht"
+
+CREATE OR REPLACE VIEW buchungsrechte_4arten AS
+ SELECT DISTINCT s.buchungsart, wb.v AS bu_art
+   FROM buchungsrechte_4wms s
+   JOIN alkis_wertearten wb
+     ON cast(s.buchungsart AS character varying) = wb.k 
+    AND wb.element = 'ax_buchungsstelle' AND wb.bezeichnung = 'buchungsart' 
+  ORDER BY buchungsart; 
+COMMENT ON VIEW buchungsrechte_4arten IS 'Vorkommende Buchungsarten bei der Verkettung von 4 Buchungsstellen.';
+-- 2302;"Wohnungs-/Teiluntererbbaurecht"
+
+
+-- Views um EinzelfÃ€lle zu suchen und aufzulisten
+-- ==============================================
+
+CREATE OR REPLACE VIEW buchungsrechte_4faelle
+AS
+ SELECT 
+    f.gml_id, f.flurstueckskennzeichen,
+    s1.laufendenummer AS bvnr1, s1.buchungsart AS buchunsart_1, w1.v AS ba1, b1.buchungsblattnummermitbuchstabenerweiterung AS blatt1,
+    s2.laufendenummer AS bvnr2, s2.buchungsart AS buchunsart_2, w2.v AS ba2, b2.buchungsblattnummermitbuchstabenerweiterung AS blatt2,
+    s3.laufendenummer AS bvnr3, s3.buchungsart AS buchunsart_3, w3.v AS ba3, b3.buchungsblattnummermitbuchstabenerweiterung AS blatt3,
+    s4.laufendenummer AS bvnr4, s4.buchungsart AS buchunsart_4, w4.v AS ba4, b4.buchungsblattnummermitbuchstabenerweiterung AS blatt4
+
+  -- FlurstÃŒck
+  FROM ax_flurstueck     f  
+
+  -- 1. Buchung
+  JOIN ax_buchungsstelle s1 ON f.istgebucht = s1.gml_id
+  LEFT JOIN alkis_wertearten  w1 ON cast(s1.buchungsart AS character varying)=w1.k AND w1.element='ax_buchungsstelle' AND w1.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt  b1 ON s1.istbestandteilvon = b1.gml_id
+
+  -- 2. Buchung
+  JOIN ax_buchungsstelle s2 ON s1.gml_id = ANY(s2.an)
+  LEFT JOIN alkis_wertearten  w2 ON cast(s2.buchungsart AS character varying)=w2.k AND w2.element='ax_buchungsstelle' AND w2.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt  b2 ON s2.istbestandteilvon = b2.gml_id
+
+  -- 3. Buchung
+  JOIN ax_buchungsstelle s3 ON s2.gml_id = ANY(s3.an)
+  LEFT JOIN alkis_wertearten  w3 ON cast(s3.buchungsart AS character varying)=w3.k AND w3.element='ax_buchungsstelle' AND w3.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt  b3 ON s3.istbestandteilvon = b3.gml_id
+
+  -- 4. Buchung
+  JOIN ax_buchungsstelle s4 ON s3.gml_id = ANY(s4.an)  
+  LEFT JOIN alkis_wertearten  w4 ON cast(s4.buchungsart AS character varying)=w4.k AND w4.element='ax_buchungsstelle' AND w4.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt  b4 ON s4.istbestandteilvon = b4.gml_id
+
+ -- nur frische Sachen
+ WHERE f.endet  IS NULL 
+   AND s1.endet IS NULL AND b1.endet IS NULL 
+   AND s2.endet IS NULL AND b2.endet IS NULL 
+   AND s3.endet IS NULL AND b3.endet IS NULL 
+   AND s4.endet IS NULL AND b4.endet IS NULL 
+ LIMIT 20;
+
+COMMENT ON VIEW buchungsrechte_4faelle IS 'FÃŒr Buchungsarten mit 4 beteiligten Buchungsstellen die einzelnen Kennzeichen tabellarisch auflisten.';
+
+
+CREATE OR REPLACE VIEW buchungsrechte_3text 
+AS
+ SELECT 
+    a3.v || ' (' || b3.blattart || ') ' || b3.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s3.laufendenummer || ') hat ' || w3.v || ' (' || s3.buchungsart || ') an ' AS stufe3,
+    a2.v || ' (' || b2.blattart || ') ' || b2.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s2.laufendenummer || ') hat ' || w2.v || ' (' || s2.buchungsart || ') an ' AS stufe2,
+    a1.v || ' (' || b1.blattart || ') ' || b1.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s1.laufendenummer || ') hat ' || w1.v || ' (' || s1.buchungsart || ') mit Buchung ' AS stufe1,
+    'FlurstÃŒck ' || f.flurstueckskennzeichen || ' (gml_id=' || f.gml_id || ')' AS flurstueck
+
+  -- FlurstÃŒck
+  FROM ax_flurstueck     f  
+
+  -- 1. Buchung
+  JOIN ax_buchungsstelle      s1 ON f.istgebucht = s1.gml_id
+  LEFT JOIN alkis_wertearten  w1 ON cast(s1.buchungsart AS character varying)=w1.k AND w1.element='ax_buchungsstelle' AND w1.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b1 ON s1.istbestandteilvon = b1.gml_id
+  LEFT JOIN alkis_wertearten  a1 ON b1.blattart=a1.k AND a1.element='ax_buchungsblatt' AND a1.bezeichnung='blattart' 
+
+  -- 2. Buchung
+  JOIN ax_buchungsstelle      s2 ON s1.gml_id = ANY(s2.an)
+  LEFT JOIN alkis_wertearten  w2 ON cast(s2.buchungsart AS character varying)=w2.k AND w2.element='ax_buchungsstelle' AND w2.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b2 ON s2.istbestandteilvon = b2.gml_id
+  LEFT JOIN alkis_wertearten  a2 ON b2.blattart=a2.k AND a2.element='ax_buchungsblatt' AND a2.bezeichnung='blattart' 
+
+  -- 3. Buchung
+  JOIN ax_buchungsstelle      s3 ON s2.gml_id = ANY(s3.an)
+  LEFT JOIN alkis_wertearten  w3 ON cast(s3.buchungsart AS character varying)=w3.k AND w3.element='ax_buchungsstelle' AND w3.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b3 ON s3.istbestandteilvon = b3.gml_id
+  LEFT JOIN alkis_wertearten  a3 ON b3.blattart=a3.k AND a3.element='ax_buchungsblatt' AND a3.bezeichnung='blattart' 
+
+ -- nur frische Sachen
+ WHERE f.endet  IS NULL 
+   AND s1.endet IS NULL AND b1.endet IS NULL 
+   AND s2.endet IS NULL AND b2.endet IS NULL 
+   AND s3.endet IS NULL AND b3.endet IS NULL 
+ LIMIT 20;
+-- AusfÃŒhrung Stadt ca. 4 Sek.
+
+COMMENT ON VIEW buchungsrechte_3text IS 'FÃŒr Buchungsarten mit 3 beteiligten Buchungsstellen die einzelnen Kennzeichen als beschreibenden Text auflisten.';
+
+
+
+CREATE OR REPLACE VIEW buchungsrechte_4text 
+AS
+ SELECT 
+    a4.v || ' (' || b4.blattart || ') ' || b4.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s4.laufendenummer || ') hat ' || w4.v || ' (' || s4.buchungsart || ') an ' AS stufe4,
+    a3.v || ' (' || b3.blattart || ') ' || b3.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s3.laufendenummer || ') hat ' || w3.v || ' (' || s3.buchungsart || ') an ' AS stufe3,
+    a2.v || ' (' || b2.blattart || ') ' || b2.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s2.laufendenummer || ') hat ' || w2.v || ' (' || s2.buchungsart || ') an ' AS stufe2,
+    a1.v || ' (' || b1.blattart || ') ' || b1.buchungsblattnummermitbuchstabenerweiterung || ' (lfd. ' || s1.laufendenummer || ') hat ' || w1.v || ' (' || s1.buchungsart || ') mit Buchung ' AS stufe1,
+    'FlurstÃŒck ' || f.flurstueckskennzeichen || ' (gml_id=' || f.gml_id || ')' AS flurstueck
+
+  -- FlurstÃŒck
+  FROM ax_flurstueck     f  
+
+  -- 1. Buchung
+  JOIN ax_buchungsstelle      s1 ON f.istgebucht = s1.gml_id
+  LEFT JOIN alkis_wertearten  w1 ON cast(s1.buchungsart AS character varying)=w1.k AND w1.element='ax_buchungsstelle' AND w1.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b1 ON s1.istbestandteilvon = b1.gml_id
+  LEFT JOIN alkis_wertearten  a1 ON b1.blattart=a1.k AND a1.element='ax_buchungsblatt' AND a1.bezeichnung='blattart' 
+
+  -- 2. Buchung
+  JOIN ax_buchungsstelle      s2 ON s1.gml_id = ANY(s2.an)
+  LEFT JOIN alkis_wertearten  w2 ON cast(s2.buchungsart AS character varying)=w2.k AND w2.element='ax_buchungsstelle' AND w2.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b2 ON s2.istbestandteilvon = b2.gml_id
+  LEFT JOIN alkis_wertearten  a2 ON b2.blattart=a2.k AND a2.element='ax_buchungsblatt' AND a2.bezeichnung='blattart' 
+
+  -- 3. Buchung
+  JOIN ax_buchungsstelle      s3 ON s2.gml_id = ANY(s3.an)
+  LEFT JOIN alkis_wertearten  w3 ON cast(s3.buchungsart AS character varying)=w3.k AND w3.element='ax_buchungsstelle' AND w3.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b3 ON s3.istbestandteilvon = b3.gml_id
+  LEFT JOIN alkis_wertearten  a3 ON b3.blattart=a3.k AND a3.element='ax_buchungsblatt' AND a3.bezeichnung='blattart' 
+
+  -- 4. Buchung
+  JOIN ax_buchungsstelle      s4 ON s3.gml_id = ANY(s4.an)  
+  LEFT JOIN alkis_wertearten  w4 ON cast(s4.buchungsart AS character varying)=w4.k AND w4.element='ax_buchungsstelle' AND w4.bezeichnung='buchungsart' 
+  JOIN ax_buchungsblatt       b4 ON s4.istbestandteilvon = b4.gml_id
+  LEFT JOIN alkis_wertearten  a4 ON b4.blattart=a4.k AND a4.element='ax_buchungsblatt' AND a4.bezeichnung='blattart' 
+
+ -- nur frische Sachen
+ WHERE f.endet  IS NULL 
+   AND s1.endet IS NULL AND b1.endet IS NULL 
+   AND s2.endet IS NULL AND b2.endet IS NULL 
+   AND s3.endet IS NULL AND b3.endet IS NULL 
+   AND s4.endet IS NULL AND b4.endet IS NULL 
+ LIMIT 20;
+-- AusfÃŒhrung Stadt ca. 2 Minuten. Wieso so lange?
+
+COMMENT ON VIEW buchungsrechte_4text IS 'FÃŒr Buchungsarten mit 4 beteiligten Buchungsstellen die einzelnen Kennzeichen als beschreibenden Text auflisten.';
+
+-- Ende --
