source: trunk/import/pp_laden.sql @ 296

Revision 296, 15.8 KB checked in by frank.jaeger, 7 years ago (diff)

PostProcesssing? Straßen-Namen, Tab pp_strassenname ersetzt ap_pto_stra

Line 
1
2-- ALKIS PostNAS 0.7
3
4-- Post Processing (pp_) Teil 2: Laden der Tabellen
5
6-- Stand
7
8--  2012-02-13 PostNAS 07, Umbenennung
9--  2012-02-17 Optimierung
10--  2012-04-17 Flurstuecksnummern auf Standardposition
11--  2012-04-24 Generell Filter 'endet IS NULL' um historische Objekte auszublenden
12--  2012-04-25 Abstürze und Fehler (durch kaputte Geometrie?) beim Zusammenfassen der Flächen
13--  2012-10-29 F.J. Redundanzen aus alkis_beziehungen beseitigen, die nach NAS replace auftreten
14--  2013-02-06 A.E. Function-Name an PostGIS 2 angepasst: multi() -> st_multi(), simplify() -> st_simplify()
15--  2013-02-21 F.J. doppelte Buchungen zum Flurstück aus alkis_beziehungen beseitigen, die nach NAS replace auftreten
16--  2013-07-10 F.J. Bereinigen der alkis_beziehungen auskommentiert, wird jetzt im Trigger gelöst.
17--  2012-10-24 Neue Tabelle für die Präsentation von Straßennamen und -Klassifikationen
18
19-- ============================
20-- Tabellen des Post-Processing
21-- ============================
22
23-- Einige Informationen liegen nach der NAS-Konvertierung in der Datenbank "verstreut" vor.
24-- Die dynamische Aufbereitung über Views und Functions würde zu lange dauern und somit lange
25-- Antwortzeiten in WMS, WFS, Buchauskunft oder Navigation (Suche) verursachen.
26
27-- Im Rahmen eines "Post-Processing" werden diese Daten nach jeder Konvertierung (NBA-Aktualisierung)
28-- einmal komplett aufbereitet. Die benötigten Informationen stehen somit den Anwendungen mundgerecht zur Verfügung.
29
30-- Die per PostProcessing gefüllten Tabellen bekommen den Profix "pp_".
31
32-- Die Ausführung dieses Scriptes auf einer Datenbank für eine 80T-Einwohner-Stadt dauert ca.: 500 Sek. !
33
34SET client_encoding = 'UTF-8';
35
36
37-- ============================================================================
38-- Redundanzen aus alkis_beziehungen beseitigen, die nach NAS replace auftreten
39-- ============================================================================
40-- Workaround: alle Redundazen nach einem Lauf entfernen.
41-- Besser wäre: sofort im Trigger bei replace entfernen.
42-- Siehe Schema in FUNCTION delete_feature_kill
43
44-- 2013-07-10 Das folgende Delete auskommentiert. Das wird jetzt im Trigger gelöst.
45------
46--      DELETE
47--        FROM alkis_beziehungen AS bezalt        -- Beziehung Alt
48--       WHERE EXISTS
49--                 (SELECT ogc_fid
50--                       FROM alkis_beziehungen AS bezneu -- Beziehung Neu
51--                      WHERE bezalt.beziehung_von = bezneu.beziehung_von
52--                        AND bezalt.beziehung_zu  = bezneu.beziehung_zu
53--                        AND bezalt.beziehungsart = bezneu.beziehungsart
54--                        AND bezalt.ogc_fid       < bezneu.ogc_fid
55--                      );
56------
57
58-- Denkbar ist eine Variante für den Trigger, die zusätzlich
59-- auf eine bestimmte gml_id filtert.
60-- Damit wäre die DB schon während der Konvertierung konsistenter.
61-- Nachtrag 2013-02-20:
62-- Diese provisorische Lösung korrigiert nur die Fälle, wo ein Replace eine redundante Beziehung
63-- einträgt. Wenn ein Objekt und seine Beziehung gleichzeitig geändert wird, wird der alte
64-- Eintrag nicht gefunden und verbleibt in den Beziehungen.
65-- Siehe z.B. in Datei "sichten.sql" die Abfrage "mehrfache_buchung_zu_fs"
66
67
68-- Mehrfache Buchungen zu einem Flurstück korrigieren.
69-- Neu 2013-02-21
70-- Dieser Fehler enststeht, wenn ein Replace zu "ax_flurstueck" gleichzeitig die
71-- Beziehung 'istGebucht' zu "ax_buchungsStelle" ändert.
72-- Kann entfallen, sobald PostNAS bei Replace die "alkis_beziehungen" richtig fortführt.
73
74-- Version Marvin Brandt, Unna
75--      DELETE
76--      --  SELECT *
77--      FROM alkis_beziehungen a1
78--      WHERE a1.beziehung_von = ANY(SELECT gml_id FROM (
79--                              SELECT f.*,
80--                                              (SELECT count(f2.gml_id) as anzahl
81--                                              FROM ax_flurstueck f2
82--                                              JOIN alkis_beziehungen a1 ON f2.gml_id = a1.beziehung_von AND a1.beziehungsart = 'istGebucht'
83--                                              WHERE f2.gml_id = f.gml_id
84--                                              ) as anzahl
85--                                      FROM ax_flurstueck f
86--                                      ) as sub
87--                              WHERE sub.anzahl > 1 )
88--      AND a1.beziehungsart = 'istGebucht'
89--      AND a1.ogc_fid = (SELECT min(sub.ogc_fid) as ogc_fid FROM (
90--              SELECT a1.*,
91--                      (SELECT count(f2.gml_id) as anzahl
92--                              FROM ax_flurstueck f2
93--                              JOIN alkis_beziehungen a1 ON f2.gml_id = a1.beziehung_von AND a1.beziehungsart = 'istGebucht'
94--                              WHERE f2.gml_id = f.gml_id
95--                      ) as anzahl
96--              FROM ax_flurstueck f
97--              JOIN alkis_beziehungen a1
98--              ON f.gml_id = a1.beziehung_von AND a1.beziehungsart = 'istGebucht'
99--              ) as sub
100--      WHERE sub.beziehung_von = a1.beziehung_von);
101
102
103-- 2013-07-10 Das folgende Delete auskommentiert. Das wird jetzt im Trigger gelöst
104------
105--      -- Version Frank Jäger, Lemgo
106--      DELETE
107--      -- SELECT *   -- TEST: erst mal schauen, was gelöscht würde, wenn ...
108--      FROM alkis_beziehungen b
109--      WHERE b.beziehungsart = 'istGebucht'
110--        -- Die erste subquery zählt die Buchungen zu einer (Flurstücks-) gml_id.
111--        -- Es wird nur dort gelöscht, wo mehrerer Buchungen existieren.
112--        AND 1 <
113--               ( SELECT count(f1.ogc_fid) AS anzfs
114--                      FROM ax_flurstueck f1
115--                      JOIN alkis_beziehungen z
116--                        ON f1.gml_id = z.beziehung_von
117--                 WHERE f1.gml_id = b.beziehung_von
118--                       AND z.beziehungsart = 'istGebucht'
119--                 GROUP BY f1.gml_id )
120--        -- Die zweite Subquery liefert die letzte (= aktuelle) Beziehung.
121--        -- Diese aktuelle Buchung wird vom Löschen ausgeschlossen.
122--        AND b.ogc_fid <
123--               ( SELECT max(a.ogc_fid) AS maxi
124--                      FROM ax_flurstueck f2
125--                      JOIN alkis_beziehungen a
126--                        ON f2.gml_id = a.beziehung_von
127--                 WHERE f2.gml_id = b.beziehung_von
128--                       AND a.beziehungsart = 'istGebucht'
129--                 GROUP BY a.beziehung_von )
130--      -- bei Test mit SELECT darf man sortieren:
131--      --  ORDER BY b.beziehung_von, b.ogc_fid
132--      ;
133------
134
135
136-- SELECT *
137--  FROM alkis_beziehungen AS bezalt
138--  WHERE EXISTS
139--        (SELECT ogc_fid
140--          FROM alkis_beziehungen AS bezneu
141--         WHERE bezalt.beziehung_von = bezneu.beziehung_von
142--           AND bezalt.beziehung_zu  = bezneu.beziehung_zu
143--           AND bezalt.beziehungsart = bezneu.beziehungsart
144--           AND bezalt.ogc_fid       < bezneu.ogc_fid
145--         );
146
147-- SELECT *
148--  FROM alkis_beziehungen AS bezalt
149--  WHERE EXISTS
150--        (SELECT ogc_fid
151--          FROM alkis_beziehungen AS bezneu
152--         WHERE bezalt.beziehung_von = bezneu.beziehung_von
153--           AND bezalt.beziehung_zu  = bezneu.beziehung_zu
154--           AND bezalt.beziehungsart = bezneu.beziehungsart
155--           AND bezalt.ogc_fid       < bezneu.ogc_fid
156--         )
157--      -- mit dem Zusatz nur die Faelle aus dem letzten Durchlauf,
158--      -- die aktuell noch in der Delet-Tabelle stehen
159--      AND EXISTS
160--         (SELECT ogc_fid
161--          FROM delete
162--          WHERE bezalt.beziehung_von = substr(featureid, 1, 16)
163--             OR bezalt.beziehung_zu  = substr(featureid, 1, 16)
164--         );
165
166
167-- =================================
168-- Flurstuecksnummern-Label-Position
169-- =================================
170
171-- ersetzt den View "s_flurstueck_nr" für WMS-Layer "ag_t_flurstueck"
172
173--DELETE FROM pp_flurstueck_nr;
174  TRUNCATE pp_flurstueck_nr;    -- effektiver als DELETE
175
176  INSERT INTO pp_flurstueck_nr
177          ( fsgml, fsnum, the_geom )
178    SELECT f.gml_id,
179           f.zaehler::text || COALESCE ('/' || f.nenner::text, '') AS fsnum,
180           p.wkb_geometry  -- manuelle Position des Textes
181      FROM ap_pto             p
182      JOIN alkis_beziehungen  v  ON p.gml_id       = v.beziehung_von
183      JOIN ax_flurstueck      f  ON v.beziehung_zu = f.gml_id
184     WHERE v.beziehungsart = 'dientZurDarstellungVon'
185       AND f.endet IS NULL
186       AND p.endet IS NULL
187     --AND p."art" = 'ZAE_NEN'
188   UNION
189    SELECT f.gml_id,
190           f.zaehler::text || COALESCE ('/' || f.nenner::text, '') AS fsnum,
191           ST_PointOnSurface(f.wkb_geometry) AS wkb_geometry  -- Flaechenmitte als Position des Textes
192      FROM      ax_flurstueck     f
193      LEFT JOIN alkis_beziehungen v  ON v.beziehung_zu = f.gml_id
194     WHERE v.beziehungsart is NULL
195       AND f.endet IS NULL
196  ;
197-- Ausführung: mittlere Stadt: ca. 4 - 18 Sec.
198
199
200-- Straßen - N a m e n  und  - K l a s s i f i k a t i o n
201-- NEU 2013-10-24
202-- Tabellen für die Präsentation von Straßen-Namen und -Klassifikationen
203-- Daten aus dem View "ap_pto_stra" werden im PostProcessing gespeichert in der Tabelle "pp_strassenname".
204-- Der View übernimmt die Auswahl des passenden "advstandardmodell" und rechnet den Winkel passend um.
205-- In der Tabelle werden dann die leer gebliebenen Label aus dem Katalog noch ergänzt.
206
207-- Tabelle aus View befüllen
208TRUNCATE pp_strassenname;
209INSERT INTO pp_strassenname (schriftinhalt, hor, ver, art, winkel, the_geom)
210       SELECT schriftinhalt, hor, ver, art, winkel, wkb_geometry
211       FROM ap_pto_stra; -- View sucht das passende advstandardmodell
212
213-- Schriftinhalt ergänzen
214--DATE ap_pto           p  -- Präsentationsobjekte Punktförmig
215UPDATE pp_strassenname  p
216   SET schriftinhalt =     -- Hier fehlt der Label
217   -- Subquery "Gib mir den Straßennamen":
218   ( SELECT k.bezeichnung                       -- Straßenname ..
219       FROM ax_lagebezeichnungkatalogeintrag k  --  .. aus Katalog
220       JOIN ax_lagebezeichnungohnehausnummer l  -- verwendet als Lage o.H.
221         ON (k.land=l.land AND k.regierungsbezirk=l.regierungsbezirk
222             AND k.kreis=l.kreis AND k.gemeinde=l.gemeinde AND k.lage=l.lage )
223       JOIN alkis_beziehungen x ON l.gml_id = x.beziehung_zu  -- Relation zum Präsentationsobjekt
224      WHERE p.gml_id = x.beziehung_von
225        AND x.beziehungsart = 'dientZurDarstellungVon'
226      -- LIMIT 1 -- war in einem Fall notwendig, wo 2mal der gleiche Text zugeordnet war, Ursache?
227   )
228 WHERE     p.schriftinhalt IS NULL
229   AND NOT p.the_geom      IS NULL;
230
231
232-- ========================================================
233-- Tabellen fuer die Zuordnung vom Gemarkungen zu Gemeinden
234-- ========================================================
235
236-- Für die Regelung der Zugriffsberechtigung einer Gemeindeverwaltung auf die
237-- Flurstücke in ihrem Gebiet braucht man die Information, in welcher Gemeinde eine Gemarkung liegt.
238-- 'ax_gemeinde' und 'ax_gemarkung' haben aber im ALKIS keinerlei Beziehung zueinander - kaum zu glauben!
239-- Nur über die Auswertung der Flurstücke kann man die Zuordnung ermitteln.
240-- Da nicht ständig mit 'SELECT DISTINCT' sämtliche Flurstücke durchsucht werden können,
241-- muss diese Information als (redundante) Tabelle nach dem Laden zwischengespeichert werden.
242
243
244-- G E M A R K U N G
245
246--DELETE FROM pp_gemarkung;
247  TRUNCATE pp_gemarkung;
248
249-- Vorkommende Paarungen Gemarkung <-> Gemeinde in ax_Flurstueck
250INSERT INTO pp_gemarkung
251  (               land, regierungsbezirk, kreis, gemeinde, gemarkung       )
252  SELECT DISTINCT land, regierungsbezirk, kreis, gemeinde, gemarkungsnummer
253  FROM            ax_flurstueck
254  WHERE           endet IS NULL
255  ORDER BY        land, regierungsbezirk, kreis, gemeinde, gemarkungsnummer
256;
257
258-- Namen der Gemarkung dazu als Optimierung bei der Auskunft
259UPDATE pp_gemarkung a
260   SET gemarkungsname =
261   ( SELECT b.bezeichnung
262     FROM    ax_gemarkung b
263     WHERE a.land=b.land
264       AND a.gemarkung=b.gemarkungsnummer
265       AND b.endet IS NULL
266   );
267
268
269-- G E M E I N D E
270
271--DELETE FROM pp_gemeinde;
272  TRUNCATE pp_gemeinde;
273
274-- Vorkommende Gemeinden aus den gemarkungen
275INSERT INTO pp_gemeinde
276  (               land, regierungsbezirk, kreis, gemeinde)
277  SELECT DISTINCT land, regierungsbezirk, kreis, gemeinde
278  FROM            pp_gemarkung
279  ORDER BY        land, regierungsbezirk, kreis, gemeinde
280;
281
282
283-- Namen der Gemeinde dazu als Optimierung bei der Auskunft
284UPDATE pp_gemeinde a
285   SET gemeindename =
286   ( SELECT b.bezeichnung
287     FROM    ax_gemeinde b
288     WHERE a.land=b.land
289       AND a.regierungsbezirk=b.regierungsbezirk
290       AND a.kreis=b.kreis
291       AND a.gemeinde=b.gemeinde
292       AND b.endet IS NULL
293   );
294
295
296-- ==============================================================================
297-- Geometrien der Flurstücke schrittweise zu groesseren Einheiten zusammen fassen
298-- ==============================================================================
299
300-- Dies macht nur Sinn, wenn der Inhalt der Datenbank einen ganzen Katasterbezirk enthält.
301-- Wenn ein Gebiet durch geometrische Filter im NBA ausgegeben wurde, dann gibt es Randstreifen,
302-- die zu Pseudo-Fluren zusammen gefasst werden. Fachlich falsch!
303
304-- Ausführungszeit: 1 mittlere Stadt mit ca. 14.000 Flurstücken > 100 Sek
305
306-- ToDo:
307--   Nur "geprüfte Flurstücke" verwenden?  Filter?
308
309--   070: TopologyException: found non-noded intersection between   ...
310
311
312DELETE FROM pp_flur;
313
314INSERT INTO pp_flur (land, regierungsbezirk, kreis, gemarkung, flurnummer, anz_fs, the_geom )
315   SELECT  f.land, f.regierungsbezirk, f.kreis, f.gemarkungsnummer as gemarkung, f.flurnummer,
316           count(gml_id) as anz_fs,
317           st_multi(st_union(st_buffer(f.wkb_geometry,0.05))) AS the_geom -- 5 cm Zugabe um Zwischenräume zu vermeiden
318     FROM  ax_flurstueck f
319     WHERE f.endet IS NULL
320  GROUP BY f.land, f.regierungsbezirk, f.kreis, f.gemarkungsnummer, f.flurnummer;
321
322-- Geometrie vereinfachen, auf 1 Meter glätten
323UPDATE pp_flur SET simple_geom = st_simplify(the_geom, 1.0);
324
325
326-- Fluren zu Gemarkungen zusammen fassen
327-- -------------------------------------
328
329-- FEHLER: 290 Absturz PG! Bei Verwendung der ungebufferten präzisen Geometrie. 
330-- bufferOriginalPrecision failed (TopologyException: unable to assign hole to a shell), trying with reduced precision
331-- UPDATE: ../../source/headers/geos/noding/SegmentString.h:175: void geos::noding::SegmentString::testInvariant() const: Zusicherung »pts->size() > 1« nicht erfüllt.
332
333
334-- Flächen vereinigen (aus der bereits vereinfachten Geometrie)
335UPDATE pp_gemarkung a
336  SET the_geom =
337   ( SELECT st_multi(st_union(st_buffer(b.simple_geom,0.1))) AS the_geom -- noch mal 10 cm Zugabe
338     FROM    pp_flur b
339     WHERE a.land      = b.land
340       AND a.gemarkung = b.gemarkung
341   );
342
343-- Fluren zaehlen
344UPDATE pp_gemarkung a
345  SET anz_flur =
346   ( SELECT count(flurnummer) AS anz_flur
347     FROM    pp_flur b
348     WHERE a.land      = b.land
349       AND a.gemarkung = b.gemarkung
350   ); -- Gemarkungsnummer ist je BundesLand eindeutig
351
352-- Geometrie vereinfachen (Wirkung siehe pp_gemarkung_analyse)
353UPDATE pp_gemarkung SET simple_geom = st_simplify(the_geom, 8.0);
354
355
356-- Gemarkungen zu Gemeinden zusammen fassen
357-- ----------------------------------------
358
359-- Flächen vereinigen (aus der bereits vereinfachten Geometrie)
360UPDATE pp_gemeinde a
361  SET the_geom =
362   ( SELECT st_multi(st_union(st_buffer(b.simple_geom,0.1))) AS the_geom -- noch mal Zugabe 10 cm
363     FROM    pp_gemarkung b
364     WHERE a.land     = b.land
365       AND a.gemeinde = b.gemeinde
366   );
367
368-- Gemarkungen zählen
369UPDATE pp_gemeinde a
370  SET anz_gemarkg =
371   ( SELECT count(gemarkung) AS anz_gemarkg
372     FROM    pp_gemarkung b
373     WHERE a.land     = b.land
374       AND a.gemeinde = b.gemeinde
375   );
376
377-- Geometrie vereinfachen (Wirkung siehe pp_gemeinde_analyse)
378UPDATE pp_gemeinde SET simple_geom = st_simplify(the_geom, 20.0);
379
380
381-- =======================================================
382-- Tabelle fuer die Zuordnung vom Eigentümern zu Gemeinden
383-- =======================================================
384
385
386-- erst mal sauber machen
387DELETE FROM gemeinde_person;
388
389-- alle direkten Buchungen mit View ermitteln und in Tabelle speichern
390-- Für eine Stadt: ca. 20 Sekunden
391INSERT INTO  gemeinde_person
392       (land, regierungsbezirk, kreis, gemeinde, person, buchtyp)
393 SELECT land, regierungsbezirk, kreis, gemeinde, person, 1
394   FROM gemeinde_person_typ1;
395
396
397-- noch die komplexeren Buchungen ergänzen (Recht an ..)
398-- Mit View ermitteln und in Tabelle speichern
399-- Für eine Stadt: ca. 10 Sekunden
400INSERT INTO  gemeinde_person
401       (  land,   regierungsbezirk,   kreis,   gemeinde,   person,  buchtyp)
402 SELECT q.land, q.regierungsbezirk, q.kreis, q.gemeinde, q.person,  2
403   FROM gemeinde_person_typ2 q   -- Quelle
404   LEFT JOIN gemeinde_person z   -- Ziel
405     ON q.person   = z.person    -- Aber nur, wenn dieser Fall im Ziel
406    AND q.land     = z.land
407    AND q.regierungsbezirk = z.regierungsbezirk
408    AND q.kreis    = z.kreis
409    AND q.gemeinde = z.gemeinde
410  WHERE z.gemeinde is Null;      -- ..  noch nicht vorhanden ist
411
412
413-- ENDE --
Note: See TracBrowser for help on using the repository browser.