Was Sie sehen, ist, dass, weil keine Ihrer Faktentabellen sich aufeinander beziehen, Sie im Wesentlichen ein kartesisches Produkt für die Faktentabellen erstellen - wo sie sich nur nach Datum beziehen.
diese vereinfachte Version Ihres Beispiel betrachte, wo ich einige Beispieldaten für „heute“ schließen auch ein:
CREATE TABLE #fact1 (id int identity, dt datetime, val varchar(5));
CREATE TABLE #fact2 (id int identity, dt datetime, val varchar(5));
CREATE TABLE #fact3 (id int identity, dt datetime, val varchar(5));
CREATE TABLE #fact4 (id int identity, dt datetime, val varchar(5));
CREATE TABLE #date (dt datetime, val varchar(5));
GO
INSERT INTO #fact1 (dt, val) VALUES (GETDATE(),'fact1');
INSERT INTO #fact2 (dt, val) VALUES (GETDATE(),'fact2');
INSERT INTO #fact3 (dt, val) VALUES (GETDATE(),'fact3');
INSERT INTO #fact4 (dt, val) VALUES (GETDATE(),'fact4');
WAITFOR DELAY '00:00:01';
GO 5
INSERT INTO #date (dt, val) VALUES (CAST(GETDATE() AS date),'Today');
GO
SELECT *
FROM #date d
JOIN #fact1 AS f1 ON d.dt = CAST(f1.dt AS date)
JOIN #fact2 AS f2 ON d.dt = CAST(f2.dt AS date)
JOIN #fact3 AS f3 ON d.dt = CAST(f3.dt AS date)
JOIN #fact4 AS f4 ON d.dt = CAST(f4.dt AS date);
GO
DROP TABLE #fact1;
DROP TABLE #fact2;
DROP TABLE #fact3;
DROP TABLE #fact4;
DROP TABLE #date;
GO
Beachten Sie, dass 625 Zeilen zurückgegeben werden. Dies ist das kartesische Produkt der vier Faktentabellen, das dann mit der Dimensionstabelle verknüpft wird. Dies geschieht, weil zwischen den Fakttabellen außer dem Datum keine Beziehung besteht. Als Ergebnis wird jede eine Zeile für "heute" in einer Faktentabelle mit jede Zeile für "heute" in jede andere Faktentabelle verbunden.
Betrachten Sie stattdessen, wie sich Ihre vier Faktentabellen OHNE den Join mit der Datumstabellen beziehen. Schreiben Sie Ihre Abfrage neu, damit die Daten vor dem Verbinden mit der Datumsdimension sinnvoll sind. Beziehen sich die Tabellen auf etwas wie eine order_id oder einen anderen Aspekt?
Wenn die Faktentabellen nur so sehr, beziehen sich, wie Sie sie nach Datum kumulieren - dann ja, müssen Sie eine andere Ansatz:
a) Aggregate nach Datum zuerst, dann kommen die aggregierten Sätze zusammen. Diese Option ist am sinnvollsten, wenn Sie nur die aggregierten Werte benötigen und nicht die vollständigen Details für Ihren Bericht benötigen.
b) Weisen Sie jedem Kalendertag eine beliebige Zeilennummer() zu und verwenden Sie diese als sekundäres Verknüpfungskriterium. Wenn sich die Daten nicht tatsächlich beziehen, funktioniert diese Option möglicherweise, aber die detaillierte Ergebnismenge ist weitgehend bedeutungslos, wenn sich alle Daten in einer einzelnen Zeile nicht auf eine einzelne Entität beziehen. Dies könnte Ihnen die richtigen Zahlen geben, ist aber logisch eine nutzlose Ergebnismenge.
SELECT *
FROM #date d
JOIN (SELECT *,
ROW_NUMBER() OVER(PARTITION BY CAST(dt AS date) ORDER BY dt) AS row_num
FROM #fact1) AS f1 ON d.dt = CAST(f1.dt AS date)
JOIN (SELECT *,
ROW_NUMBER() OVER(PARTITION BY CAST(dt AS date) ORDER BY dt) AS row_num
FROM #fact2) AS f2 ON d.dt = CAST(f2.dt AS date) AND f1.row_num = f2.row_num
JOIN (SELECT *,
ROW_NUMBER() OVER(PARTITION BY CAST(dt AS date) ORDER BY dt) AS row_num
FROM #fact3) AS f3 ON d.dt = CAST(f3.dt AS date) AND f1.row_num = f3.row_num
JOIN (SELECT *,
ROW_NUMBER() OVER(PARTITION BY CAST(dt AS date) ORDER BY dt) AS row_num
FROM #fact4) AS f4 ON d.dt = CAST(f4.dt AS date) AND f1.row_num = f4.row_num
c) Unterteilen Sie dies in separate Anweisungen: eine für jede Faktentabelle. Optional UNION
diese Ergebnisse in einer einzigen Ergebnismenge. Diese Ergebnismenge könnte dann weiter aggregiert/gruppiert werden, um Ihnen die gewünschten Ergebnisse zu liefern.
SELECT *, 'Fact 1' AS SourceTable
FROM #date d
JOIN #fact1 AS f1 ON d.dt = CAST(f1.dt AS date)
UNION ALL
SELECT *, 'Fact 2' AS SourceTable
FROM #date d
JOIN #fact2 AS f2 ON d.dt = CAST(f2.dt AS date)
UNION ALL
SELECT *, 'Fact 3' AS SourceTable
FROM #date d
JOIN #fact3 AS f3 ON d.dt = CAST(f3.dt AS date)
UNION ALL
SELECT *, 'Fact 4' AS SourceTable
FROM #date d
JOIN #fact4 AS f4 ON d.dt = CAST(f4.dt AS date);
Meiner Meinung nach, Optionen ein & c die besten Lösungen anzubieten, wenn die Faktentabellen sonst nicht miteinander in Beziehung stehen. Option b funktioniert möglicherweise, aber Sie müssen sehr vorsichtig sein, dass Ihre Daten aussagekräftig sind & erstellt keine verwirrenden oder fehlerhaften Ergebnisse.
Beachten Sie außerdem, dass die Anwendung einer Funktion auf ein Join-Kriterium (in diesem Fall CONVERT
in der Datumsspalte) die Indexnutzung verhindert, was zu einem Tabellenscan führt.
Nicht verwandt mit Ihrer Frage, aber warum speichern Sie Datumsangaben als Zeichenfolgen in Ihrer Dimensionstabelle? –
Datumsangaben sind Datumsangaben, keine Zeichenketten, die Konvertierung soll den Zeitteil entfernen. –
Ich denke, dass Ihre mehreren Faktentabellen kollidieren. Wenn Sie sich vorstellen können, dass der Mocdate-Tisch nur zwei Zeilen enthält, die beide das Datum 01.01.2016 haben. Wenn Sie nur die Datendimension zu mocdate hinzufügen, erhalten Sie 2 Datenzeilen zurück. Nun stellen Sie sich vor, senddate hat nur eine Zeile Daten, auch für 1/1/2016. Wenn Sie jetzt senddate der oben erstellten virtuellen Tabelle beitreten, erhalten Sie 2 Zeilen von senddate, da es aufgrund von mocdate bereits 2 Zeilen gibt. – Bostaevski