SQL Tipp #001 – Data Profiling

Eine typische Tätigkeit im Rahmen der fachlichen Konzeption ist auch die Systemanalyse – auch wenn viele Autoren oder Experten anderer Meinung sind und eher eine strikte Trennung zwischen Business Analyse und System Analyse für sinnvoll erachten. Meiner Meinung nach macht es keinen Sinn, eine scharfe Trennlinie zu ziehen. Bereits in der Phase der Anforderungsanalyse und der entsprechenden Dokumentation (Fachkonzept) ist es äußerst hilfreich und angebracht in Datenvorräte „hineinzuschauen“, um bereits zu einem sehr frühen Zeitpunkt die Machbarkeit zu prüfen und gegebenenfalls darauf zu reagieren. So werden keine „Luftschlösser“ gebaut und falsche oder etwa überzogene Erwartungshaltungen entstehen erst gar nicht. Natürlich sollte man in der Phase der Fachkonzeption die Aufwände für die Systemanalyse nicht ausufern lassen. Aber oftmals reicht ja bereits eine Stichprobe, um ein „Gefühl“ für die Daten zu bekommen. Ideal ist es, wenn die Quellsystemdaten bereits in einem relationalen Datenbank-System vorliegen, so dass mit Standard SQL Abfragen darauf zugegriffen werden kann. Vielleicht steht ja auch noch ein komfortabler SQL Editor zur Verfügung. In meinen Augen ein sehr wichtiges Werkzeug für jeden BI Business Analysten.

Soweit so gut. Der Zugriff auf die Daten ist also gegeben. Jetzt geht es darum, sich schnell einen Überblick über die Daten zu verschaffen. Typische Fragen hierbei sind:

  • Welche Entitäten enthalten welche Datenstrukturen?
  • Was ist der fachlich eindeutige Schlüssel einer Entität (Business Key)
  • Wie stehen die Entitäten in Beziehung zueinander?
  • Welche Daten (Ausprägungen) enthalten die einzelnen Attribute (Tabellen-Spalten)?
  • Wie verteilen sich die einzelnen Ausprägungen prozentual? (Ausprägungskardinalität)
  • Welche Ausreißer gibt es?

Das wissen um die Kardinalität ist bespielsweise sehr wichtig für eine korrekte und performante Datenmodellierung. Die obigen Fragen gehören zum Themengebiet des „Data Profiling„. Spezielle Tools hierfür sind auf dem Software-Markt erhältlich. Informatica bietet zum Beispiel sein Produkt „Data Analyst“ an, früher bekannt unter „Informatica Data Explorer“ (IDE). Es bietet sich an, den Fachbereich in den Profiling Prozess direkt miteinzubinden bzw. auch ihm das Profiling Werkzeug zur Verfügung zu stellen. Schließlich kennt er die Daten in der Regel am besten. Und falls nicht, so lernt er sie durch das Profiling sehr gut kennen. Leider ist ein dediziertes Profiling Tool nicht immer vorhanden – und an dieser Stelle kommt der heutige SQL Tipp zum Zug. Das nachfolgende SQL Skript liefert einen schnellen Überblick über die Daten – ähnlich wie ein professionelles Profiling Tool es tun würde.

Nun zum Skript: Die Grundidee ist, das Data Dictionary der Datenbank zu verwenden, um sich das Profiling Skript dynamisch generieren zu lassen. D.h. die einzelnen Spalten einer Tabelle werden nicht manuell für jede zu untersuchende Tabelle angepasst, sondern aus dem Dictionary geholt.

Schritt 1: Dynamischer Aufbau des Profiling SQLs. Eingabe Parameter sind Schema Name (DM_ALL) und der Tabellenname (td_d_par_org_mm) in Zeile 4

-- dynamisch Query erzeugen
WITH 
 tmptable (tmp_schema, tmp_table, tmp_count) AS 
 (VALUES('mySchema', 'myTable', (select count (*) from mySchema.myTable as tmp_count)))
SELECT 
 -- dynamischer Aufbau eines SQL SELECT Statements
 'select sub.*, CEILING((sub.Anzahl / CAST('|| sub.tmp_count ||
 ' AS DECFLOAT)  * 100))  || ''%'' as Anteil from (select ' || 
 sub.COLNAME || ', count(COALESCE(' || sub.COLNAME || ',-9)) as Anzahl from '|| 
 sub.tmp_schema ||'.'|| sub.tmp_table ||' group by ' || sub.COLNAME || ') sub order by 2 desc;'
FROM (
  SELECT 
   colname, tmp_schema, tmp_table, tmp_count
  FROM 
   syscat.columns, tmptable
  WHERE 
   tabschema = tmp_schema and tabname = tmp_table
  ORDER BY 
   colno  
) sub
;

Schritt 2: Pro Tabellenspalte wird ein SQL generiert. Nachfolgend ist das  SQL Statement nur einer Spalte abgebildet (in dem Fall für die Spalte myColumn):

 -- so sieht die dynamisch generierte Query aus
select 
 sub.*
,CEILING((sub.Anzahl / CAST(266 AS DECFLOAT)  * 100))  || '%' as Anteil 
from (
 select 
  myColumn
 ,count(COALESCE(myColumn,-9)) as Anzahl 
 from 
  mySchema.myTable 
 group by 
  myColumn
 ) sub 
order by 
 2 desc
;

Schritt 3: Kopiert man nun die generierten SQL in den Editor und führt diese wiederum aus, so erhält man für jede einzelne Spalte einer Tabelle ein Profiling wie im nachfolgenden Screenshot dargestellt.

Das Skript wurde getestet mit IBM DB2 v9.7

Schlagwörter: