prog:sql_oracle_pattern_matching
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende Überarbeitung | Nächste ÜberarbeitungBeide Seiten der Revision | ||
prog:sql_oracle_pattern_matching [2019/07/29 22:42] – gpipperr | prog:sql_oracle_pattern_matching [2019/08/06 20:42] – gpipperr | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | =====Oracle SQL Pattern Matching Funktion in der Praxis einsetzen===== | ||
+ | |||
+ | ===Aufgabe=== | ||
+ | |||
+ | Auf einer Tabelle mit Kontodaten soll ermittelt werden, wie viele Tage ein Kunden von wann bis wann in der Vergangenheit im Verzug war. | ||
+ | |||
+ | |||
+ | (Fachliches Thema im Detail siehe => https:// | ||
+ | |||
+ | |||
+ | Mit PL/SQL kann nun zum Beispiel einfach ein Zähler über alle Stichtage auf der Konto Tabelle laufen und je nach Kontostand einen Zähler hochzählen. | ||
+ | |||
+ | Wie kann das aber für Analysen auch in SQL gelöst werden? | ||
+ | |||
+ | |||
+ | Hier bietet sich das Feature Oracle Pattern Matching an. | ||
+ | |||
+ | |||
+ | Wir suchen folgendes Muster in den Daten: | ||
+ | |||
+ | |||
+ | * Aktueller Stichtag Kontostand unter 0 => Start Zähler Kontostand unter 0 | ||
+ | * Solange weitere Stichtage untersuchen, | ||
+ | | ||
+ | Ausgabe: Von wann bis wann war das Konto überzogen | ||
+ | |||
+ | |||
+ | Lösung mit Oracle SQL Pattern Matching: | ||
+ | <code sql> | ||
+ | select * | ||
+ | from konten | ||
+ | | ||
+ | -- gruppiern nach kundennummer | ||
+ | PARTITION BY KDNR order by datum | ||
+ | -- Was messen wir | ||
+ | MEASURES | ||
+ | , first(DowABSLimit.datum) | ||
+ | , last(DowABSLimit.datum) | ||
+ | , first(UPABSLimit.datum) | ||
+ | , last(UPABSLimit.datum) | ||
+ | , next(UPABSLimit.datum) | ||
+ | , trunc(first(UPABSLimit.datum)) - trunc(first(DowABSLimit.datum)) | ||
+ | , round(avg(DowABSLimit.BETRAG)) as avg_BETRAG | ||
+ | , MATCH_NUMBER() as match_number | ||
+ | , CLASSIFIER() as classifier | ||
+ | one row per match | ||
+ | -- for anlayse show all values between | ||
+ | -- all rows per match | ||
+ | after match skip to last UPABSLimit | ||
+ | -- define the check pattern | ||
+ | pattern (STRT DowABSLimit+ UPABSLimit+ ) | ||
+ | SUBSET STDN= (STRT, DowABSLimit) | ||
+ | -- rules for pattern | ||
+ | DEFINE | ||
+ | DowABSLimit | ||
+ | , | ||
+ | ) KTO | ||
+ | order by 2 desc | ||
+ | ; | ||
+ | |||
+ | </ | ||
+ | |||
+ | Wie erstellen wir aber so ein komplexes SQL und wie stellen wir fest ob das so überhaupt funktioniert? | ||
+ | |||
+ | ---- | ||
+ | |||
+ | |||
+ | ==== Lösungsweg ==== | ||
+ | |||
+ | SQL Pattern Matching gehört nicht zu den selbsterklärenden Featuren der Oracle Datenbank. alleine einen Einsatzzweck oder gar ein Beispiel zu finden, das nicht die üblichen Börsenkurs oder Wetter Schwankungen beinhaltet, ist schwer. | ||
+ | |||
+ | |||
+ | Um das ganze besser zu verstehen habe ich mir einen Test Daten Satz für ein fiktives Konto erzeugt, die erzeugten Daten nach Excel geladen und visualisiert und dann per SQL Abfrage auf die Test Tabelle geprüft, ob das gewünschte Ergebnis auch erzielt werden kann. | ||
+ | |||
+ | |||
+ | === Test Daten generieren === | ||
+ | |||
+ | |||
+ | Anlegen einer Test Tabelle Konten und füllen mit zufälligen Werten: | ||
+ | <code sql> | ||
+ | create table Konten ( | ||
+ | KDNR number(11) | ||
+ | , datum date | ||
+ | , betrag number(11, | ||
+ | ) | ||
+ | ; | ||
+ | |||
+ | declare | ||
+ | v_val number(11, | ||
+ | v_datum date: | ||
+ | begin | ||
+ | |||
+ | for i in 1 .. 1000 | ||
+ | loop | ||
+ | |||
+ | v_val: | ||
+ | v_datum: | ||
+ | |||
+ | if mod(i,50)=0 then | ||
+ | v_val: | ||
+ | end if; | ||
+ | |||
+ | dbms_output.put_line(' | ||
+ | |||
+ | insert into konten ( KDNR, datum, betrag) values (1000, v_datum ,v_val ); | ||
+ | |||
+ | end loop; | ||
+ | |||
+ | end; | ||
+ | / | ||
+ | </ | ||
+ | |||
+ | CSV eerzugen um nach Excel zu laden: | ||
+ | <code sql> | ||
+ | SET echo off | ||
+ | SET verify off | ||
+ | SET feedback off | ||
+ | SET heading off | ||
+ | set termout off | ||
+ | set markup CSV ON | ||
+ | |||
+ | spool import_to_excel.csv | ||
+ | |||
+ | select to_char(datum,' | ||
+ | , | ||
+ | from konten | ||
+ | order by datum desc | ||
+ | / | ||
+ | |||
+ | spool off | ||
+ | |||
+ | set markup CSV OFF | ||
+ | set termout ON | ||
+ | SET feedback ON | ||
+ | SET heading ON | ||
+ | SET echo ON | ||
+ | SET verify ON | ||
+ | |||
+ | </ | ||
+ | |||
+ | In Excel eine Bereich der Daten visualisieren: | ||
+ | |||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | Wir wollen zum Beispiel genau diesen Datenbereich finden: | ||
+ | {{ : | ||
+ | |||
+ | |||
+ | Mit der SQL Query von oben klappt das. | ||
+ | |||
+ | |||
+ | Aber warum und wie funktioniert das ganze überhaupt? | ||
+ | |||
+ | |||
+ | Hier nochmal unsere Abfrage: | ||
+ | <code sql> | ||
+ | select * | ||
+ | from konten | ||
+ | | ||
+ | | ||
+ | -- gruppiern nach kundennummer und Zeilen nach Datum sortieren | ||
+ | -- pro Row in der Partition wird das Pattern angewandt | ||
+ | PARTITION BY KDNR order by datum | ||
+ | | ||
+ | -- Was messen wir wenn das Pattern gefunden werden kann | ||
+ | MEASURES | ||
+ | , first(DowABSLimit.datum) | ||
+ | , last(DowABSLimit.datum) | ||
+ | , first(UPABSLimit.datum) | ||
+ | , last(UPABSLimit.datum) | ||
+ | , next(UPABSLimit.datum) | ||
+ | , trunc(first(UPABSLimit.datum)) - trunc(first(DowABSLimit.datum)) | ||
+ | , round(avg(DowABSLimit.BETRAG)) as avg_BETRAG | ||
+ | , MATCH_NUMBER() as match_number | ||
+ | , CLASSIFIER() as classifier | ||
+ | | ||
+ | -- Pro Treffer eine Zeile anzeigen | ||
+ | one row per match | ||
+ | -- for anlayse show all values between | ||
+ | --all rows per match | ||
+ | | ||
+ | -- was soll nach dem ersten Match passieren | ||
+ | after match skip to last UPABSLimit | ||
+ | | ||
+ | -- das eigentliche Pattern | ||
+ | pattern (STRT DowABSLimit+ UPABSLimit+ ) | ||
+ | | ||
+ | -- für den Anfang der Daten sicherstellen das .. | ||
+ | --SUBSET NAME_SUBSET= (STRT, DowABSLimit) | ||
+ | | ||
+ | -- Das Pattern definieren | ||
+ | DEFINE | ||
+ | DowABSLimit | ||
+ | , | ||
+ | ) KTO | ||
+ | |||
+ | order by 2 desc | ||
+ | ; | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Erläuterungen zum Einsatz von Oracle SQL Pattern Matching ==== | ||
+ | |||
+ | Die Schritte beim Pattern Match | ||
+ | |||
+ | .. demnächst mehr | ||
+ | |||
+ | ---- | ||
+ | |||
+ | |||
+ | ==== Quellen ==== | ||
+ | |||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | Doku: | ||
+ | * https:// |
prog/sql_oracle_pattern_matching.txt · Zuletzt geändert: 2020/09/30 14:19 von gpipperr