Warning: Trying to access array offset on value of type null in /var/www/apps/geoport/lib/plugins/wikiformatstyling/syntax/nwtag.php on line 48
Warning: Trying to access array offset on value of type null in /var/www/apps/geoport/lib/plugins/wikiformatstyling/syntax/nwtag.php on line 48
Inhaltsverzeichnis
Vollhistorie von Tabellen mit beginnt/endet Zeitstempel
Vollhistorie mit einer Tabelle
CAST beginnt/endet AS text
SELECT * FROM alkis.ax_grenzpunkt WHERE CASE WHEN '$hist_timestamp' = ''::text THEN endet IS NULL ELSE beginnt::text <= '$hist_timestamp' AND ('$hist_timestamp' < endet::text OR endet IS NULL) END;
Nachteil: Die date-Felder beginnt und endet werden für den Vergleich in das Text-Format umgewandelt. Das kostet Zeit und macht sich bei großen Datensatzmengen deutlich bemerkbar.
CAST $hist_timestamp AS timestamp
SELECT * FROM alkis.ax_grenzpunkt WHERE CASE WHEN '$hist_timestamp' = ''::text THEN endet IS NULL ELSE beginnt <= NULLIF('$hist_timestamp', '')::timestamp AND (NULLIF('$hist_timestamp', '')::timestamp < endet OR endet IS NULL) END;
Nachteil: Die WHERE-Klausel wird unübersichtlich. Wenn zwei Tabellen abgefragt werden, ist das WHERE gerade noch so verständlich, ab drei verknüpften Tabellen wirds völlig unübersichtlich.
CAST beginnt und endet AS tsrange
SELECT * FROM alkis.ax_grenzpunkt WHERE tsrange(beginnt, endet) @> COALESCE(NULLIF('$hist_timestamp', '')::timestamp, localtimestamp);
Vorteil: Die WHERE-Bedingung mit tsrange arbeitet deutlich schneller. Die Übersichtlichkeit bleibt auch bei mehreren verknüpften Tabellen erhalten.
Vollhistorie über mehrere Tabellen
CAST beginnt/endet AS text
SELECT * FROM alkis.ax_grenzpunkt AS g JOIN alkis.ax_punktortta AS p ON g.gml_id = ANY (p.istteilvon) WHERE CASE WHEN '$hist_timestamp' = '' THEN g.endet IS NULL AND p.endet IS NULL ELSE g.beginnt::text <= '$hist_timestamp' AND ('$hist_timestamp' < g.endet::text OR g.endet IS NULL) AND p.beginnt::text <= '$hist_timestamp' AND ('$hist_timestamp' < p.endet::text OR p.endet IS NULL) END;
Nachteil: Im „historischen Fall“ (dem ELSE-Zweig) werden alle Stände der ersten Tabelle und alle Fälle der zweiten Tabelle ermittelt und dann miteinander zu Objekten verknüpft - egal, ob sie zeitgleich existierten oder zeitlich nichts miteinander zu tun haben. Das generiert etliche überflüssige „Treffer“, die gar keine sind.
CAST beginnt und endet AS tsrange
SELECT * FROM alkis.ax_grenzpunkt AS g JOIN alkis.ax_punktortta AS p ON g.gml_id = ANY (p.istteilvon) AND tsrange(g.beginnt, g.endet) && tsrange(p.beginnt, p.endet) WHERE tsrange(g.beginnt, g.endet) * tsrange(p.beginnt, p.endet) @> COALESCE(NULLIF('$hist_timestamp', '')::timestamp, localtimestamp);
Vorteil: Der Vergleich der Lebenszeitintervalle der Objekte aus der ersten und aus der zweiten Tabelle liefert nur die Objekte, die gleichzeitig existierten (&&
= a intersects b). In der WHERE-Bedingung wird nur das gemeinsame Lebenszeitintervall des verknüpften Objekts gegen $hist_timestamp geprüft (*
= Intersection von a und b).
Operatoren auf range-Datentypen
Rückgabe-Datentyp ''boolean''
=
(equal),<>
(not equal),<
(less than),>
(greater than),<=
(less than or equal) und>=
(greater than or equal)&&
(overlap) und-|-
(is adjacent to)<@
(is contained by) und@>
(contains)«
(strictly left of) und»
(strictly right of)&<
(does not extend to the right of) und&>
(does not extend to the left of)
Rückgabe-Datentyp ''range''
*
(intersection)+
(union)-
(difference)
Performance-Verbesserung von range-Operationen
Anlegen eines funktionalen Index:
CREATE INDEX idx_ax_grenzpunkt_range_gist ON alkis.ax_grenzpunkt USING gist (tsrange(beginnt, endet));
Die range-Operatoren =
, &&
, -|-
, <@
, @>
, «
, »
und &<
nutzen gist
- und sp_gist
-Indizes.