我们最近创建了一个SSAS表格模型,因此我们的用户可以通过PowerView访问它。我们对其中一个事实表进行度量以TotalActiveItems
使用公式:
TotalActive:=COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)
这可以根据需要很好地工作,但是现在我们要求获得每月的前10名父母TotalActive
。
供参考,这是我们模型的一部分:
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与表和示例数据。
该factStats
表有FKS的DevID
,CustID
,BillDateTimeID
,和ParentID
。我们的要求是基于AND,Top 10 Parents
为每个计算或存储,并在汇总类别中包括前10名中未包括的所有内容,类似于以下内容:BillDateTimeID
TotalActive
+----------------+------------+------+
| BillDateTimeID | Parent | Rank |
+----------------+------------+------+
| 20140801 | Jim | 1 |
| 20140801 | Bob | 2 |
| 20140801 | All Others | 3 |
+----------------+------------+------+
我可以使用窗口功能轻松地在SQL中完成此操作,但是尝试为SSAS重现此操作很困难。在SQL中,我们将使用以下方法获得结果:
;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;
我尝试了几种不同的方法来获得结果,但是每种方法都有一个问题。我的尝试如下。
最初,我能够使用MDX查询获得数据,但后来不知道如何将其合并到表格模型中。供参考的MDX查询为:
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]};
当然,这也只给我一个月的结果,而不是每个月。
当我意识到MDX查询将不起作用时,我从更改factStats
表开始,以包括一个新列来标记前10名和汇总值中的项目。
alter table factStats
add Top10ParentID INT NOT NULL
constraint DF_factStats default (0);
默认约束引用了前10名的“ Rolled Up”值。
尝试1: 我创建了新的前10个表来存储ParentID,名称和排名:
create table dimTop10Parent
(
Top10ParentID INT NOT NULL PRIMARY KEY,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL
);
每次我们根据新的“前10个父级”父项拥有的“活动总数”项刷新模型时,就会填充该表。Parent_Rank
然后,该列将隐藏在我们的表格模型中,仅用于排序。这非常有效,但由于我们不是按月计算,因此我们无法从历史上获得前十名。
尝试#2:创建一个新表来存储前10名,但是主键将同时包含Top10ParentID和BillingDateTimeID。
create table dimTop10Parent
(
Top10ParentID INT NOT NULL,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL,
BillDateTimeID BIGINT NOT NULL
);
问题是我们无法在表格模型的dimTop10Parent中的factStats单个FK与两个部分PK之间建立关系。
尝试#3:创建新表,但使用身份作为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
);
该factStats
表将存储Top10ID
每行唯一的值。我以为这可以解决我的问题,但是,这并不是因为我们无法再按Parent_Rank
模型中的进行排序,它会引发错误:
无法通过Parent_Rank对ParentName进行排序,因为ParentName中的至少一个值在Parent_Rank中具有多个不同的值。例如,您可以按[地区]对[城市]进行排序,因为每个城市只有一个地区,但是您不能按[城市]对[地区]进行排序,因为每个地区有多个城市。
使用样本数据,最终结果应该类似于(显示前2名,排名第3):
| 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 |
在这一点上,我对如何获得最终结果一无所知。我可以改变表格需要得到它,我可以用一个公式,措施等我改变模型读过关于使用DAX口诀排名1,2,3,但我似乎无法总结我的头周围他们足够能够准确地获得结果。
我该如何计算/存储任何月份的前10名,并且仍然能够按照表格模型的需要拼接数据?