Wir haben kürzlich ein tabellarisches SSAS-Modell erstellt, damit unsere Benutzer über PowerView darauf zugreifen können. Wir haben ein Maß für eine unserer Faktentabellen, um die TotalActiveItems
Verwendung einer Formel zu ermitteln:
TotalActive:=COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)
Das funktioniert nach Bedarf sehr gut, aber jetzt haben wir die Bitte, die Top 10 Eltern für jeden Monat in der Liste zu bekommen TotalActive
.
Als referenz, hier ist teil unseres modells:
create table factStats
(
StatsID INT IDENTITY NOT NULL PRIMARY KEY,
DevID INT NOT NULL,
DeactDate DATETIME NULL,
BillDateTimeID BIGINT NOT NULL,
CustID INT NOT NULL,
ParentID INT NOT NULL
);
create table dimCust
(
CustID INT NOT NULL PRIMARY KEY,
CustName varchar(150) NOT NULL
);
create table dimParent
(
ParentID INT NOT NULL PRIMARY KEY,
ParentName varchar(100) NOT NULL
);
create table dimDateTime
(
DateTimeID BIGINT NOT NULL PRIMARY KEY
);
SQL Fiddle mit Tabellen und Beispieldaten.
Die factStats
Tabelle hat FKs auf die DevID
, CustID
, BillDateTimeID
, und ParentID
. Die Anforderung, die wir haben, besteht darin, die Werte Top 10 Parents
für jedes ElementBillDateTimeID
basierend auf dem TotalActive
UND zu berechnen oder zu speichern. Dies umfasst alles, was nicht in den Top 10 enthalten ist, in einer zusammengefassten Kategorie, die der folgenden ähnelt:
+----------------+------------+------+
| BillDateTimeID | Parent | Rank |
+----------------+------------+------+
| 20140801 | Jim | 1 |
| 20140801 | Bob | 2 |
| 20140801 | All Others | 3 |
+----------------+------------+------+
Ich kann dies in SQL leicht mit Hilfe von Fensterfunktionen erreichen, aber der Versuch, dies für SSAS zu reproduzieren, war schwierig. In SQL erhalten wir das Ergebnis mit:
;with Total as
(
select
ParentID,
BillDateTimeID,
sum(case when DeactDate is null then 1 else 0 end) TotalActive
from factStats
group by ParentID, BillDateTimeID
),
PRank as
(
select
ParentID,
BillDateTimeID,
TotalActive,
row_number() over(partition by BillDateTimeID
order by TotalActive desc) pr
from total
)
select
parentid,
BillDateTimeID,
TotalActive,
pr
from prank
where pr <= 2
union all
select
0,
BillDateTimeID,
sum(TotalActive) TotalActive,
3
from prank
where pr > 2
group by BillDateTimeID
order by BillDateTimeID desc, pr;
Ich habe verschiedene Wege ausprobiert, um das Ergebnis zu erhalten, aber jeder hatte ein Problem. Meine Versuche sind unten.
Anfangs konnte ich die Daten mit einer MDX-Abfrage etwas abrufen, hatte dann aber keine Ahnung, wie ich sie in unser Tabellenmodell integrieren sollte. Die MDX-Abfrage als Referenz lautet:
with
set [Top10Parent] AS
(
(TOPCOUNT({ORDER(({[Parent].[Parent Name].[Parent Name]}),
([Measures].[Total Count]), BDESC)}, 10))
)
MEMBER [Parent].[Parent Name].[Others] AS
(
AGGREGATE(EXCEPT([Parent].[Parent Name].[Parent Name], [Top10Parent]))
)
select
[Measures].[Total Count] on columns,
{[Top10Parent]}+ {[Parent].[Parent Name].[Others]} on Rows
from [OurModel]
where {[Date and Time].[Month and Year].[Month and Year].[Jul 2014]};
Natürlich gab mir dies auch nur das Ergebnis für einen einzigen Monat, nicht jeden Monat.
Als ich feststellte, dass die MDX-Abfrage nicht funktionieren würde, änderte ich zunächst unsere factStats
Tabelle, um eine neue Spalte einzuschließen, in der die Elemente in den Top 10 und im zusammengefassten Wert gekennzeichnet werden.
alter table factStats
add Top10ParentID INT NOT NULL
constraint DF_factStats default (0);
Die Standardbedingung bezieht sich auf unseren "Aufgerollten" Wert für die Top 10.
Versuch Nr. 1: Ich habe eine neue Top 10-Tabelle erstellt, um die ParentID, den Namen und den Rang zu speichern:
create table dimTop10Parent
(
Top10ParentID INT NOT NULL PRIMARY KEY,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL
);
Diese Tabelle wird dann jedes Mal ausgefüllt, wenn wir unser Modell mit den neuen Top-10-Eltern aktualisieren, basierend auf den insgesamt aktiven Elementen, die sie haben. Die Parent_Rank
Spalte wird dann in unserem Tabellenmodell ausgeblendet und ausschließlich zum Sortieren verwendet. Dies funktioniert hervorragend, es sei denn, wir haben nicht die Möglichkeit, die Top 10 in der Vergangenheit zu erreichen, da dies nicht auf monatlicher Basis erfolgt.
Versuch Nr. 2: Erstellen Sie eine neue Tabelle zum Speichern der Top 10, aber der Primärschlüssel enthält sowohl die Top10ParentID als auch eine BillingDateTimeID.
create table dimTop10Parent
(
Top10ParentID INT NOT NULL,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL,
BillDateTimeID BIGINT NOT NULL
);
Das Problem dabei ist, dass wir im dimTop10Parent im tabellarischen Modell keine Beziehung zwischen den factStats single FK und der zweiteiligen PK erstellen können.
Versuch 3: Erstellen Sie die neue Tabelle, verwenden Sie jedoch eine Identität als PK.
create table dimTop10Parent
(
Top10ID INT IDENTITY NOT NULL PRIMARY KEY,
Top10ParentID INT NOT NULL,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL,
BillDateTimeID BIGINT NOT NULL
);
In der factStats
Tabelle wird der Top10ID
Wert gespeichert, der für jede Zeile eindeutig ist. Ich dachte, dies würde mein Problem lösen, aber es war nicht so, weil wir nicht mehr nach dem Parent_Rank
im Modell sortieren können , es wirft einen Fehler auf:
ParentName kann nicht nach Parent_Rank sortiert werden, da mindestens ein Wert in ParentName mehrere unterschiedliche Werte in Parent_Rank enthält. Beispielsweise können Sie [Stadt] nach [Region] sortieren, da es nur eine Region für jede Stadt gibt, Sie können [Region] jedoch nicht nach [Stadt] sortieren, da es für jede Region mehrere Städte gibt.
Unter Verwendung der Beispieldaten sollte das Endresultat ähnlich sein (dies zeigt Top 2 mit einem 3. Rollup):
| PARENTNAME | BILLDATETIMEID | TOTALACTIVE | PR |
|------------|----------------|-------------|----|
| FDN | 201408010000 | 11 | 1 |
| FDO | 201408010000 | 3 | 2 |
| All Others | 201408010000 | 5 | 3 |
| FDN | 201407010000 | 12 | 1 |
| EVOD | 201407010000 | 2 | 2 |
| All Others | 201407010000 | 5 | 3 |
Zu diesem Zeitpunkt bin ich nicht sicher, wie ich dieses Endergebnis erzielen soll. Ich kann die Tabellen nach Bedarf ändern, ich kann das Modell mithilfe einer Formel, eines Maßes usw. ändern. Ich habe gelesen, wie man mit den DAX-Formeln 1 , 2 , 3 rangiert , aber ich kann meinen Kopf nicht umklammern sie genug, um das Ergebnis genau zu erhalten.
Wie kann ich diese Top 10 für einen Monat berechnen / speichern und trotzdem in der Lage sein, die Daten nach Bedarf in unserem tabellarischen Modell zusammenzufügen?