如何在表格模型中计算/存储前10名?


23

我们最近创建了一个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的DevIDCustIDBillDateTimeID,和ParentID。我们的要求是基于ANDTop 10 Parents为每个计算或存储,并在汇总类别中包括前10名中未包括的所有内容,类似于以下内容:BillDateTimeIDTotalActive

+----------------+------------+------+
| 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;

SQL提琴演示

我尝试了几种不同的方法来获得结果,但是每种方法都有一个问题。我的尝试如下。

最初,我能够使用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口诀排名123,但我似乎无法总结我的头周围他们足够能够准确地获得结果。

我该如何计算/存储任何月份的前10名,并且仍然能够按照表格模型的需要拼接数据?

Answers:


1

我有类似的情况,并使用以下DAX查询...

首先,为简单起见,我定义了一种在DAX中使用的度量,因此不必重复公式。然后,我使用generate来迭代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

有了以上内容,您应该每月获得前10个ParentID和Measure。只需将表格“ TableInTabular”替换为您具有数据的表格表名称,将“ DatesTableName”替换为日期表的名称即可。

如果我误解了您的问题,请告诉我,希望对您有所帮助。


1
感谢您的回答,与此有关的还有一些问题。首先,我可以在SSMS中使用它,但是它已被部署到我们的表格模型中,因此我们的用户可以通过PowerView进行访问-他们不会编写任何查询-这仅需要可用。其次,除非我做错了事,否则通过Visual Studio在表格模型中不允许进行任何评估或排序-此功能没有选项。第三,此查询仅返回前10名,我还需要汇总数据或某种方式来获取它。不过,我将继续处理。
塔林
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.