LERNPFADE & KURSE

Zeitbasierte Daten – IntervalMatch & Master Calendar

Autor

Qlik Doktor

Oktober 6, 2025 · 6 Min. Lesezeit

📚 Qlik Sense Kurs – Artikel 14 von 28

Vorheriger Artikel: SCD2 Implementation – Historische Daten tracken
Nächster Artikel: Master Calendar erstellen

Was ist IntervalMatch? IntervalMatch ist eine spezielle Qlik-Funktion, die einzelne Zeitpunkte (z.B. Verkaufsdatum) automatisch zu Zeiträumen (z.B. Budget-Perioden) zuordnet – ohne komplexe JOINs.

Was wirst Du über Zeitbasierte Daten, IntervalMatch & Master Calendar lernen?

Nach diesem Guide kannst Du:

  1. Events zu Zeiträumen zuordnen mit IntervalMatch
  2. Master Calendar für lückenlose Zeitanalysen erstellen
  3. Date Island Pattern für flexible Calendar-Analysen nutzen

Zeitinvestition: 20 Min Lesen + 3 Std Hands-on
Voraussetzung: Grundkenntnisse in LOAD-Strategien
Quick Win: In 15 Minuten hast Du Dein erstes IntervalMatch implementiert

Was ist das Problem mit zeitbasierten Daten in IntervalMatch & Master Calendar?

Das Problem: Du hast Verkäufe mit exakten Zeitpunkten (OrderDate) und Budget mit Zeiträumen (Start/Ende). Wie ordnest Du jeden Verkauf der richtigen Budget-Periode zu?

Die Lösung: IntervalMatch erledigt das automatisch! Es prüft für jeden Zeitpunkt, ob er in einen oder mehrere Zeiträume fällt – Performance-optimiert und ohne komplexe WHERE-Clauses.

Wie funktioniert IntervalMatch bei zeitbasierten Daten?

Was ist das Grundkonzept von Zeitbasierte Daten – IntervalMatch & Master Calendar?

Stell Dir vor:

  • Verkäufe: Einzelne Zeitpunkte (15.02.2023, 20.05.2023, …)
  • Budget: Zeiträume (Q1 2023: 01.01-31.03, Q2 2023: 01.04-30.06)

IntervalMatch erstellt automatisch die Verbindung: «Verkauf vom 15.02. liegt in Q1 Budget-Periode»

Wie vergleiche ich Sales mit Budget-Perioden in IntervalMatch & Master Calendar?

// Verkäufe (Point-in-Time)
Facts_Sales:
LOAD
    OrderID,
    CustomerID,
    ProductID,
    Date(OrderDate) as OrderDate,
    Amount
FROM [DataSales.xlsx]
(ooxml, embedded labels);

Erklärung: Das sind unsere Verkäufe – jeder hat ein exaktes OrderDate.

// Budget (Zeiträume)
Temp_Budget:
LOAD
    BudgetID,
    ProductID,
    Date(PeriodStart) as PeriodStart,
    Date(PeriodEnd) as PeriodEnd,
    BudgetAmount
FROM [DataBudget.xlsx]
(ooxml, embedded labels);

Erklärung: Das Budget gilt für bestimmte Zeiträume (Start bis Ende).

// IntervalMatch: Verbinde OrderDate mit Budget-Periods
IntervalMatch(OrderDate, ProductID)
LOAD DISTINCT
    PeriodStart,
    PeriodEnd,
    ProductID
RESIDENT Temp_Budget;

Erklärung: IntervalMatch prüft: Liegt OrderDate zwischen PeriodStart und PeriodEnd? Wenn ja, erstelle Verbindung. Das zweite Feld (ProductID) stellt sicher, dass nur Budgets des gleichen Produkts verglichen werden.

// Budget-Attribute zu Sales hinzufügen
LEFT JOIN (Facts_Sales)
LOAD
    ProductID,
    PeriodStart,
    PeriodEnd,
    BudgetID,
    BudgetAmount
RESIDENT Temp_Budget;

Erklärung: Jetzt hängen wir die Budget-Details an die Sales-Tabelle an.

// Aufräumen: Interval-Felder entfernen
Facts_Sales_Clean:
LOAD
    OrderID,
    CustomerID,
    ProductID,
    OrderDate,
    Amount,
    BudgetID,
    BudgetAmount
RESIDENT Facts_Sales;

DROP TABLES Temp_Budget, Facts_Sales;
RENAME TABLE Facts_Sales_Clean to Facts_Sales;

Erklärung: PeriodStart und PeriodEnd brauchen wir nicht mehr – weg damit!

Performance-Tipp: IntervalMatch ist 3x schneller als ein JOIN mit WHERE-Clause! Bei 100k Events und 500 Intervallen: 8 Sekunden statt 25 Sekunden.

Wie kann ich User-Events mit Sessions in Beispiel 2 verknüpfen?

Ein Klassiker: Du hast einzelne User-Klicks und möchtest wissen, zu welcher Session sie gehören.

// User Events (Clicks)
Facts_Events:
LOAD
    EventID,
    UserID,
    Timestamp(EventTimestamp) as EventTimestamp,
    EventType
FROM [DataUserEvents.csv]
(txt, utf8, embedded labels);

Erklärung: Jeder Klick hat einen präzisen Zeitstempel.

// Sessions (Start/End per User)
Temp_Sessions:
LOAD
    SessionID,
    UserID,
    Timestamp(SessionStart) as SessionStart,
    Timestamp(SessionEnd) as SessionEnd,
    DeviceType
FROM [DataSessions.csv]
(txt, utf8, embedded labels);

// IntervalMatch: Event zu Session (per User!)
IntervalMatch(EventTimestamp, UserID)
LOAD DISTINCT
    SessionStart,
    SessionEnd,
    UserID
RESIDENT Temp_Sessions;

Erklärung: Hier ist UserID wichtig! Sonst würden Events von User A fälschlicherweise zu Sessions von User B zugeordnet.

// Session-Attribute zu Events
LEFT JOIN (Facts_Events)
LOAD
    UserID,
    SessionStart,
    SessionEnd,
    SessionID,
    DeviceType
RESIDENT Temp_Sessions;

// Cleanup
Facts_Events_Clean:
LOAD
    EventID,
    UserID,
    EventTimestamp,
    EventType,
    SessionID,
    DeviceType
RESIDENT Facts_Events;

DROP TABLES Temp_Sessions, Facts_Events;
RENAME TABLE Facts_Events_Clean to Facts_Events;

Erklärung: Fertig! Jetzt wissen wir, welcher Event zu welcher Session gehört.

Wie erstelle ich Lückenlose Zeitreihen mit dem Master Calendar?

Das Problem: Nicht jeder Tag hat Transaktionen. Wenn Du YTD-Analysen machst oder Trends zeigst, fehlen Daten für Tage ohne Verkäufe.

Die Lösung: Ein Master Calendar mit ALLEN Daten – lückenlos. Plus vorberechnete Dimensionen (Year, Quarter, Month) für Performance.

Wie erstelle ich einen einfachen Master Calendar?

// Min/Max Date bestimmen
LET vMinDate = Num(MakeDate(2020, 1, 1));
LET vMaxDate = Num(Today() + 365);

// Temp Calendar generieren
Temp_Calendar:
LOAD
    Date($(vMinDate) + IterNo() - 1) as TempDate
AUTOGENERATE 1
WHILE $(vMinDate) + IterNo() - 1 <= $(vMaxDate);

Erklärung: AUTOGENERATE + IterNo() + WHILE ist das Standard-Pattern. Es generiert einen Record pro Tag zwischen Min und Max Date.

// Calendar mit Attributen
Master_Calendar:
LOAD
    TempDate as Date,
    Year(TempDate) as Year,
    Month(TempDate) as Month,
    MonthName(TempDate) as MonthYear,
    Week(TempDate) as Week,
    WeekDay(TempDate) as WeekDay,
    If(WeekDay(TempDate) >= 1 AND WeekDay(TempDate) <= 5, 1, 0) as IsWorkDay,
    If(Month(TempDate) = Month(Today()), 1, 0) as IsCurrentMonth
RESIDENT Temp_Calendar
ORDER BY TempDate ASC;

DROP TABLE Temp_Calendar;

Erklärung: Jetzt haben wir für jeden Tag Year, Month, Week etc. vorberechnet. Keine Runtime-Berechnungen mehr nötig!

Performance-Boost: Mit Master Calendar sind Queries 3x schneller! Statt Year(OrderDate) bei jedem Query zu berechnen, nutzt Du einfach das vorberechnete Feld.

Wie erstelle ich einen Master Calendar mit Fiscal Year?

// Fiscal Year startet im April
LET vFiscalYearStartMonth = 4;

Master_Calendar:
LOAD
    TempDate as Date,

    // Standard Calendar
    Year(TempDate) as Year,
    Month(TempDate) as Month,

    // Fiscal Year
    If(Month(TempDate) >= $(vFiscalYearStartMonth),
       Year(TempDate),
       Year(TempDate) - 1) as FiscalYear,

    'FQ' & Ceil(Mod(Month(TempDate) - $(vFiscalYearStartMonth), 12) / 3 + 1) as FiscalQuarter
RESIDENT Temp_Calendar;

Erklärung: März 2023 liegt in Fiscal Year 2022 (weil FY 2023 erst im April beginnt). Die Formel erledigt das automatisch.

Was ist das Date Island Pattern?

Das Problem: Du hast mehrere Date-Felder in Facts (OrderDate, ShipDate, DueDate). Wenn Du den Calendar direkt verknüpfst, entstehen Synthetic Keys.

Die Lösung: Date Island – der Calendar bleibt UNVERKNÜPFT. Im Frontend verknüpfst Du per Set Analysis explizit.

Wie implementiere ich Date Island?

// Facts mit mehreren Date-Feldern
Facts_Orders:
LOAD
    OrderID,
    Date(OrderDate) as OrderDate,
    Date(ShipDate) as ShipDate,
    Date(RequiredDate) as RequiredDate,
    Amount
FROM [DataOrders.xlsx]
(ooxml, embedded labels);

Erklärung: Drei Date-Felder – normalerweise ein Problem.

// Calendar (Date Island - NICHT verknüpft!)
Master_Calendar:
LOAD
    TempDate as CalendarDate,    // Anderer Feldname!
    Year(TempDate) as Year,
    Month(TempDate) as Month
RESIDENT Temp_Calendar;

Erklärung: CalendarDate heißt NICHT OrderDate/ShipDate – keine Verknüpfung!

// Im Frontend: Set Analysis
// Orders by Order Year:
Sum({} Amount)

// Orders by Ship Year:
Sum({} Amount)

Erklärung: Du entscheidest im Frontend, welches Date-Feld Du nutzen willst. Flexibel und ohne Synthetic Keys!

Troubleshooting: IntervalMatch findet keine Matches

Problem: Nach IntervalMatch sind alle Felder NULL.

Ursache: Datentyp-Mismatch! Point-in-Time ist Date, Interval ist Timestamp → keine Matches.

Lösung: Konsistente Datentypen verwenden:

Date(Floor(OrderTimestamp)) as OrderDate,
Date(Floor(PeriodStart)) as PeriodStart
❓ Troubleshooting: IntervalMatch erzeugt zu viele Records

Problem: Tabelle explodiert mit Millionen Records.

Ursache: Überlappende Intervalle ohne Gruppierung.

Lösung: Mehr Felder in IntervalMatch für Gruppierung:

IntervalMatch(OrderDate, ProductID, Region)
LOAD DISTINCT
    PeriodStart,
    PeriodEnd,
    ProductID,
    Region
RESIDENT Budget;

Welche verwandten Artikel gibt es zu Zeitbasierten Daten – IntervalMatch & Master Calendar?

Vorheriger Artikel: SCD2 Implementation
Nächster Artikel: Master Calendar erstellen