Tar*_*ryn 23 ssas tabular-model
我们最近创建了一个 SSAS 表格模型,以便我们的用户可以通过 PowerView 访问它。我们对我们的一个事实表进行了测量,以TotalActiveItems使用公式获取:
TotalActive:=COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)
Run Code Online (Sandbox Code Playgroud)
这在需要时非常有效,但现在我们有一个请求,以获取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
);
Run Code Online (Sandbox Code Playgroud)
SQL 摆弄表格和示例数据。
该factStats表有FKS的DevID,CustID,BillDateTimeID,和ParentID。我们的请求是基于计算或存储Top 10 Parents每个BillDateTimeID的TotalActive 并且将不在前 10 名中的所有内容包含在类似于以下的汇总类别中:
+----------------+------------+------+
| BillDateTimeID | Parent | Rank |
+----------------+------------+------+
| 20140801 | Jim | 1 |
| 20140801 | Bob | 2 |
| 20140801 | All Others | 3 |
+----------------+------------+------+
Run Code Online (Sandbox Code Playgroud)
我可以使用窗口函数在 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;
Run Code Online (Sandbox Code Playgroud)
我尝试了几种不同的方法来获得结果,但每种方法都有问题。我的尝试如下。
最初,我能够使用 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]};
Run Code Online (Sandbox Code Playgroud)
当然,这也只给了我一个月的结果,不是每个月。
当我意识到 MDX 查询不起作用时,我开始更改我们的factStats表以包含一个新列来标记前 10 名和汇总值中的项目。
alter table factStats
add Top10ParentID INT NOT NULL
constraint DF_factStats default (0);
Run Code Online (Sandbox Code Playgroud)
默认约束引用了前 10 名的“Rolled Up”值。
尝试 #1: 我创建了新的 Top 10 表来存储 ParentID、姓名和排名:
create table dimTop10Parent
(
Top10ParentID INT NOT NULL PRIMARY KEY,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
每次我们使用新的前 10 个父项刷新我们的模型时,都会根据它们拥有的总活动项填充此表。Parent_Rank然后该列隐藏在我们的表格模型中,专门用于排序。这很好用,除了我们没有能力在历史上获得前 10 名,因为它不是基于逐月计算的。
尝试 #2:创建一个新表来存储前 10 个,但 PRIMARY KEY 将包括 Top10ParentID 和 BillingDateTimeID。
create table dimTop10Parent
(
Top10ParentID INT NOT NULL,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL,
BillDateTimeID BIGINT NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
这样做的问题是我们无法在表格模型中的 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
);
Run Code Online (Sandbox Code Playgroud)
该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 |
Run Code Online (Sandbox Code Playgroud)
在这一点上,我对如何得到这个最终结果感到茫然。我可以根据需要更改表格以获取它,我可以使用公式、度量等更改模型。我已经阅读了有关使用 DAX 公式1、2、3 进行排名的文章,但我似乎无法理解它们足以能够准确地得到结果。
我如何计算/存储任何月份的前 10 名,并且仍然能够在我们的表格模型中根据需要拼接数据?
小智 1
我有一个类似的场景并使用了以下 DAX 查询...
首先,为了简单起见,我定义了一个在 DAX 内部使用的度量,这样我就不必重复公式。然后我使用生成来迭代 TOPN 公式:
define measure TableInTabular[NameOfTheMeasure] = COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)
evaluate
(
addcolumns
(
filter
(
generate
(
VALUES(DatesTableName[Month]),
TOPN (10, VALUES(TableInTabular[ParentID]),TableInTabular[NameOfTheMeasure],0)
),
TableInTabular[NameOfTheMeasure]>0
),
"ActiveCount (or how you want to call this Column)",
TableInTabular[NameOfTheMeasure]
)
)
order by DatesTableName[Month] asc,
TableInTabular[NameOfTheMeasure] desc
Run Code Online (Sandbox Code Playgroud)
通过上述内容,您应该获得前 10 个 ParentID 和每个月的度量。只需将“TableInTabular”替换为包含数据的表格名称,将“DatesTableName”替换为日期表的名称。
如果我误解了您的问题,请告诉我并希望它有所帮助......