Jahreswerte auf Monate verlustfrei verteilen – Teil 1

Ich habe wieder ein schönes Beispiel gefunden an der man die Flexibilität der Integration Services demonstrieren kann. Die Aufgabe ist recht einfach: es geht darum, einen Jahreswert mit Dezimalstellen (in unserem Fall ein numeric(6,2), z.B. ein Euro-Wert) gleichmäßig auf 12 Monate zu verteilen. Die Division sollte uns hoffentlich keine Kopfschmerzen bereiten, die Herausforderung liegt darin, dass unser Datentyp nur zwei Nachkommastellen erlaubt und daher viele Werte bei der Division einen Genauigkeitsverlust erleiden würden.

Ein kurzes Beispiel: teilen wir den Wert 100,00  ?¬ durch 12 erhalten wir pro Monat einen Wert von 8,3333.  ?¬ Würden wir nun 12 mal den Wert 8,33  ?¬ als Monatswert in unsere Datenbank übernehmen, würden uns über das Jahr hinweg gesehen 0,04  ?¬ fehlen. Das Ziel wäre hier, diese 4 Eurocent (also den Differenzbetrag) auf den letzten Monat aufzuschlagen.

 

Das Problem begegnet uns immer dann, wenn in der Datenbank Werte in einer anderen Granularität gespeichert werden (in diesem Fall monatsgenau) als diese von der darauf aufsetzenden Anwendung geliefert werden (diese erlaubt nur jahresgenaue Werte). Für spätere Auswertungen oder Ã?nderungen möchten wir monatsgenaue Werte speichern, ohne den korrekten Jahreswert (die Summe der 12 Monate) zu verlieren.

 

Auch hier führen wieder viele Wege nach Rom, daher zeige ich im ersten Teil neben der eigentlichen Problemstellung und dem Kern der Lösung eine von vier (!) Möglichkeiten die ich gefunden habe um die Aufgabe zu lösen.

 

Zunächst einmal überlege ich mir geeignete Ausdrücke um die oben genannte Anforderung innerhalb eines SSIS-Datenfluss‘ umsetzen zu können. Für die Monate 1 bis 11 genügt folgender Ausdruck:

 

(DT_NUMERIC,6,2)(Value / 12)

 

Der Monat 12 erfordert eine Sonderbehandlung, welche durch folgenden Ausdruck gewährleistet wird:

 

(DT_NUMERIC,6,2)(Value – (DT_NUMERIC,6,2)(11 * (DT_NUMERIC,6,2)(Value / 12)))

 

Im Grunde ermittelt dieser Ausdruck die Differenz zwischen dem Jahreswert und der Summe der 11 Monatswerte um den Wert für Monat 12 zu berechnen. Beachten Sie dabei, dass es egal ist ob bei der Ermittlung der Monatswerte ab- oder aufgerundet oder gar abgeschnitten wird (was hier der Fall ist), der Wert für Monat 12 wird stets korrekt ermittelt.

 

Einer der naheliegendsten Wege um diese Logik umzusetzen ist die Nutzung eines Cross Joins zwischen dem Jahreswert und 12 Monaten. Damit wird der Jahreswert von einer Zeile auf 12 Zeilen verteilt. Anschließend kann in einem „Abgeleitete Spalte“-Task der Wert mit Hilfe der oben beschriebenen Ausdrücke manipuliert werden.

 

Folgender Screenshot zeigt den Datenfluss und zwei Data Viewer: einen nach dem Cross Join und einem nach dem Anwenden der Ausdrücke. Beachten Sie, dass sich der Wert für Monat 12 von allen anderen unterscheidet um einen korrekten Jahreswert zu gewährleisten.

 

image

 

Im zweiten Teil zeige ich drei (!) weitere Vorgehensweisen, sowie die Ergebnisse eines Performancetests um zu ermitteln, wie sich die unterschiedlichen Wege im produktiven Einsatz bewähren könnten.


Schreibe einen Kommentar