MDX++ trifft Tabular: Aggregationen der nächsten Generation

David Alvarez Debrot
David Alvarez Debrot
August 21, 2025

INHALTSVERZEICHNIS
icCube. MDX++ trifft Tabular
Analytik
OLAP
Technologie
Alle

Die Idee ist, dass Sie sich keine Gedanken mehr über die zugrunde liegende Technologie machen müssen, „Analysieren Sie einfach.“ Das ist die übliche Tonhöhe — und obwohl sie mehr oder weniger wahr ist, ist die Realität nuancierter.

Wo das Modell seine Risse zeigt

So mächtig das dimensionale Modell auch ist, es weist Mängel auf. Ein triviales, aber übliches ist das Berechnung eines gewichteten Durchschnitts.

  • MDX unterstützt technisch gewichtete Durchschnittswerte, allerdings nur auf der Grundlage von Dimensionselementen, nicht auf Zeilenebene.
  • Die Leistung verschlechtert sich, wenn im Durchschnitt Hunderttausende (oder sogar Millionen) von Objekten verarbeitet werden.
  • Standardmäßig verarbeitet MDX Summen, Anzahlen und Durchschnittswerte, aber keine zeilenbasierten gewichteten Durchschnittswerte.

Die übliche Problemumgehung:

  • Fügen Sie eine berechnete Spalte auf Zeilenebene hinzu (Wert × Gewicht)
  • Das multidimensionale Modell, dargestellt durch MDX, bietet Endbenutzern eine sehr bequeme Möglichkeit, Daten abzufragen. Sobald das Modell erstellt ist, können Benutzer Felder einfach per Drag-and-Drop verschieben und die Engine die Berechnungen durchführen lassen.
  • Wenn das Modell aggregiert, dividieren Sie die summierten Produkte durch das Gesamtgewicht.

Das funktioniert, aber es ist klobig, fehleranfällig und bläht das Modell auf.

Und das ist nur der einfacher Fall. Reale Anforderungen benötigen oft eine Logik, die nicht gut mit dem OLAP zusammenpasst „Erst aggregieren, später berechnen“ philosophie.

Komplexere Szenarien

1. Umrechnungen von Devisen (FX)

Finanztransaktionen, die in mehreren Währungen aufgezeichnet wurden, erfordern Konvertierung auf Zeilenebene vor der Aggregation.

  • Wenn Sie EUR-Transaktionen summieren und dann zum Zeitpunkt der Abfrage einen „durchschnittlichen“ Wechselkurs anwenden, sind die Ergebnisse falsch.
  • Für die Genauigkeit muss zuerst der richtige Tageskurs pro Zeile angewendet und dann aggregiert werden.

2. Zeitabhängige Anpassungen

Werte müssen häufig durch Faktoren angepasst werden, die sich im Laufe der Zeit ändern:

  • Regulatorische Koeffizienten
  • Inflationsfaktoren
  • Produktspezifische Multiplikatoren

Wenn sie auf aggregierter Ebene angewendet werden, sind die Ergebnisse verzerrt. Jede Zeile muss vor dem Rollup mit ihrem Faktor multipliziert werden.

3. Immobilienverwaltung (Kundenfall)

Ein anderer zeitabhängiges Szenario ist, wenn Werte für alle Daten zwischen einem bestimmten Startdatum und Enddatum gültig sind.

Ein Kunde aus der realen Welt hat Mietdaten in einem Delta-Modell gespeichert: Nur Änderungen (Mieterhöhung, Änderung der Heizkosten usw.) wurden gespeichert.

Bei der Berichterstattung sind jedoch monatliche Beträge erforderlich. Aktuelle Problemumgehungen:

  • Vorab berechnen volle Werte für jeden Monat (enorme Speicherkosten).
  • Benutzerdefinierte Java-MDX-Funktion mit icCube-Vektoren (chaotische, knifflige Nullbehandlung).

Beides sind Kompromisse. Was benötigt wird, ist Aggregation auf Zeilenebene direkt im Modell.

Die Lösung: MDX++ trifft Tabular

Version 9 führt eine Funktion ein, mit der Benutzer ein Objekt definieren können, das Daten zeilenweise aggregiert, indem die in der Faktentabelle einer Maßgruppen definierten Spalten verwendet werden.

  • Aggregationen sind definiert in Java-Code.
  • Kompiliert und optimiert wie die interne Engine von icCube.
  • Keine aufgeblähten Modelle oder Vorverarbeitung mehr.

Jetzt können Sie die Logik auf Zeilenebene innerhalb des tabellarischen Modells selbst definieren. Die Engine führt die Aggregation automatisch durch.

Praktische Ergebnisse

  • Gewichtete Durchschnittswerte → Der Motor verwaltet intern Wert × Gewicht + Gewicht→ jedes Mal das richtige Verhältnis.
  • FX-Konvertierungen → Betrag jeder Zeile × täglicher Wechselkurs, der auf Zeilenebene angewendet wird → genaue Summen.
  • Zeitbasierte Anpassungen → Pro Zeile angewendete Multiplikatoren → konsistente Ergebnisse im Laufe der Zeit.
  • Verwaltung von Immobilien → Delta-basierter Speicher wird ohne Speicherüberflutung zu monatlichen Werten.

Hinzufügen eines Tabellenaggregators

Diese Funktion ist immer noch Alpha, also brauchst du ein bisschen Java-Code.

Schritt 1: Klasse mit gewichtetem Durchschnitt erstellen

public class WeightedAverage implements IOlapFactTableAggregatorFactory {
   @Override
   public IOlapFactTableAggregator newInstance() {
       return new IOlapFactTableAggregator() {
           int weightIdx;
           int valueIdx;
           double weightedSum = 0;
           double weight = 0;

           @Override
           public String getName() {
               return "WeightedAverage";
           }

           @Override
           public void init(IFactTableContext namesToArrayPosition, String measureName, String factColumnName) {
               weightedSum = weight = 0;
               weightIdx = namesToArrayPosition.getFromColumnName("weight");
               valueIdx = namesToArrayPosition.getFromColumnName("amount");
           }

           @Override
           public boolean onRow(int rowNumber, IOlapFactsTableRow row) {
               final double w = row.getAsDouble(weightIdx);
               weight += w;
               weightedSum += w * row.getAsDouble(valueIdx);
               return true;
           }

           @Override
           public OlapScalarEntity asScalarEntity() {
               return weight == 0
                   ? null
                   : new OlapNumericEntity(weightedSum / weight);
           }
       };
   }
}

Schritt 2: Klasse hinzufügen plugin.xml

<tableAggregator name="WeightedAverage" className="com.myamazing.WeightedAverage"/>

Schritt 3: Aggregation in MDX überschreiben

CREATE SET_TABLE_AGGREGATOR [Measures].[Weighted Amount] ‘WeightedAverage’

Ergebnis

Analysten profitieren immer noch von der Einfachheit per Drag-and-Drop — allerdings mit Berechnungen, die Respekt zollen Datenkomplexität in der realen Welt.

  • Keine Abkürzungen mehr, die „gut genug“ sind.
  • Nur genaue Zahlen, jedes Mal.

Die Zukunft

  • Fügen Sie die Möglichkeit hinzu, die Klasse direkt im Schema zu definieren.
  • Erweitern Sie die Sprache, um Syntax wie die folgende zu ermöglichen:

MEASURE [Weighted Amount] AS    
   AGGREGATE ROWS SUM([amount] * [weight]) / SUM([weight])

Dieser Blog wurde mit Hilfe einer KI geschrieben. Dabei wurde keine KI geschädigt (nur ein paar CPUs sind überhitzt).

Sie finden unsere Artikel hilfreich?
Abonniere unseren Newsletter, um nie einen zu verpassen!