我要求按客户群显示前5位客户销售额,但与其他客户在集团内的销售额汇总为“其他”。与this question类似,但为每个客户群分别计算。
根据MSDN执行TopCount,对于一组成员,您必须使用Generate function。
这部分工作正常:
with
set [Top5CustomerByGroup] AS
GENERATE
(
[Klient].[Grupa Klientow].[Grupa Klientow].ALLMEMBERS,
TOPCOUNT
(
[Klient].[Grupa Klientow].CURRENTMEMBER * [Klient].[Klient].[Klient].MEMBERS
, 5
, [Measures].[Przychody ze sprzedazy rzeczywiste wartosc]
)
)
SELECT
{ [Measures].[Przychody ze sprzedazy rzeczywiste wartosc]} ON COLUMNS,
{
[Klient].[Grupa Klientow].[Grupa Klientow].ALLMEMBERS * [Klient].[Klient].[All], --for drilldown purposes
[Top5CustomerByGroup]
}
ON ROWS
FROM
(
SELECT ({[Data].[Rok].&[2013]} ) ON COLUMNS
FROM [MyCube]
)
然而我对'其他'部分有疑问。
我认为我能够按组建立与其他客户的集合(数据看起来不错):
set [OtherCustomersByGroup] AS
GENERATE
(
[Klient].[Grupa Klientow].[Grupa Klientow].ALLMEMBERS,
except
(
{[Klient].[Grupa Klientow].CURRENTMEMBER * [Klient].[Klient].[Klient].MEMBERS},
TOPCOUNT
(
[Klient].[Grupa Klientow].CURRENTMEMBER * [Klient].[Klient].[Klient].MEMBERS
, 5
, [Measures].[Przychody ze sprzedazy rzeczywiste wartosc]
)
)
)
但是我不知道如何将其与分组聚合在一起。
中执行此操作member [Klient].[Klient].[tmp] as
aggregate([OtherCustomersByGroup])
生成一个值,这是合乎逻辑的。
我认为我需要在每个组中使用“其他”客户的集合列表,而不是单个[OtherCustomersByGroup]
集合,但不知道如何构建它们。
有没有人有任何想法或建议?
更新
对我的需求存在一些误解。我需要通过销售来满足每个客户群中的前N个客户,并将该组中其他客户的销售汇总到一个位置(假设称为其他)。
例如,对于此简化输入:
| Group | Client | Sales |
|--------|----------|--------|
| Group1 | Client1 | 300 |
| Group1 | Client2 | 5 |
| Group1 | Client3 | 400 |
| Group1 | Client4 | 150 |
| Group1 | Client5 | 651 |
| Group1 | Client6 | null |
| Group2 | Client7 | 11 |
| Group2 | Client8 | 52 |
| Group2 | Client9 | 44 |
| Group2 | Client10 | 21 |
| Group2 | Client11 | 201 |
| Group2 | Client12 | 325 |
| Group2 | Client13 | 251 |
| Group3 | Client14 | 15 |
我需要这样的输出(这里是前2名):
| Group | Client | Sales |
|--------|----------|--------|
| Group1 | Client5 | 651 |
| Group1 | Client3 | 400 |
| Group1 | Others | 455 |
| Group2 | Client12 | 325 |
| Group2 | Client13 | 251 |
| Group2 | Others | 329 |
| Group3 | Client14 | 15 |
| Group3 | Others | null | <- optional row
不需要排序,我们将在客户端处理它。
答案 0 :(得分:3)
是的,您通过使用SET for Others获得了主要想法,但完成任务需要几个小的补充。
我将使用我的测试数据库,但这可以很容易地转换为你的。
[Report Date]
- 日期维度([Klient]
analogue)[REPORT DATE Y]
- 年等级([Grupa Klientow]
)[REPORT DATE YM]
- 月份层次结构([Klient].[Klient]
)[Measures].[Count]
- 衡量TopCount([Measures].[Przychody ze sprzedazy rzeczywiste wartosc]
)我也使用前三名来显示结果图片。
这是代码:
with
/* first, add empty [Other] member to the group level */
member [Report Date].[REPORT DATE Y].[Other] as null
/* second, copy measure by fixing the lowest level */
member [Measures].[Count with Other Groups] as ([Report Date].[REPORT DATE YM],[Measures].[Count])
/* third, create top 10 by group */
set [Report Date Top 10 Groups] as
Generate([Report Date].[REPORT DATE Y].Children
,TopCount([Report Date].[REPORT DATE Y].CurrentMember
* [Report Date].[REPORT DATE YM].Children,3,[Measures].[Count with Other Groups]))
/* this is the part for Other group mapping */
set [Report Date Other Groups] as
[Report Date].[REPORT DATE Y].[Other]
* ([Report Date].[REPORT DATE YM].Children
- Extract([Report Date Top 10 Groups],[Report Date].[REPORT DATE YM]))
select {[Measures].[Count],[Measures].[Count with Other Groups]} on 0
,
{
[Report Date Top 10 Groups],[Report Date Other Groups]}
on 1
from
[DATA]
结果如下:
..直到最后一位(即201606)的所有成员都在Other
组。
希望这有帮助,bardzodziękuję!
通过删除Report Date Other Groups
计算中的一个乘法来优化更新代码。
更新-2 :(尚未解决,但正在进行中)
(在每组下使用'其他'成员)
重要!我们需要额外的层次结构:Group->Client
([Report Date].[REPORT DATE]
,Year->Month
是我的情况),以便能够为每个低级别成员确定父级。
with
/* create top 10 by group */
set [Report Date Top 10 Groups] as
Generate([Report Date].[REPORT DATE Y].Children
,TopCount([Report Date].[REPORT DATE Y].CurrentMember
* [Report Date].[REPORT DATE].Children,3,[Measures].[Count]))
/* this is the part for Other group the lowest level non-aggregated members */
set [Report Date Other Members] as
[Report Date].[REPORT DATE Y].Children
* ([Report Date].[REPORT DATE].[Month].AllMembers
- [Report Date].[REPORT DATE].[All])
- [Report Date Top 10 Groups]
/* add empty [Other] member to the group level, HERE IS AN ISSUE */
member [Report Date].[REPORT DATE].[All].[Other] as null
set [Report Date Other Groups] as
[Report Date].[REPORT DATE Y].[All].Children
* [Report Date].[REPORT DATE].[Other]
member [Measures].[Sum of Top] as
IIF([Report Date].[Report Date].CurrentMember is [Report Date].[REPORT DATE].[Other]
,null /* HERE SHOULD BE CALCULATION, but only
{[Report Date].[Report Date Y].[All].[Other]}
is shown, because 'Other' is added to the entire hierarchy */
,SUM([Report Date].[REPORT DATE Y].CurrentMember
* ([Report Date].[Report Date].CurrentMember.Parent.Children
- Extract([Report Date Other Members],[Report Date].[REPORT DATE]))
,[Measures].[Count]))
member [Measures].[Sum of Group] as
([Report Date].[Report Date].CurrentMember.Parent,[Measures].[Count])
select {[Measures].[Count],[Measures].[Sum of Group],[Measures].[Sum of Top]} on 0
,
Order(Hierarchize({[Report Date Top 10 Groups]
,[Report Date Other Groups]}),[Measures].[Count],DESC)
on 1
from
[DATA]
这是中间结果:
我需要在此处移动此结果,但不知道该怎么做。
我也尝试过使用每个级别的平面层次结构。 Other
成员显示正确,但无法计算SUM,因为两个级别都是独立的。也许我们可以添加像'Group_Name'这样的属性并使用未链接的级别,但是再次 - 它会大大降低性能。所有这些IIF([bla-bla-bla low level member].Properties("Group_Name")=[bla-bla-bla group level].Member_Name
都非常慢。
Update-3(上述代码的AdvWorks版本)
with
/* create top 10 by group */
set [Top 10 Groups] as
Generate([Customer].[Country].Children
,TopCount([Customer].[Country].CurrentMember
* [Customer].[Customer Geography].Children,3,[Measures].[Internet Order Count]))
/* this is the part for Other group the lowest level non-aggregated members */
set [Other Members] as
[Customer].[Country].Children
* ([Customer].[Customer Geography].[State-Province].AllMembers
- [Customer].[Customer Geography].[All])
- [Top 10 Groups]
/* add empty [Other] member to the group level */
member [Customer].[Customer Geography].[All].[Other] as
([Customer].[Country],[Measures].[Internet Order Count])
set [Other Groups] as
[Customer].[Country].[All].Children
* [Customer].[Customer Geography].[Other]
member [Measures].[Sum of Top] as
IIF([Customer].[Customer Geography].CurrentMember is [Customer].[Customer Geography].[Other]
,null
,SUM([Customer].[Country].CurrentMember
* ([Customer].[Customer Geography].CurrentMember.Parent.Children
- Extract([Other Members],[Customer].[Customer Geography]))
,[Measures].[Internet Order Count]))
member [Measures].[Sum of Group] as
([Customer].[Customer Geography].CurrentMember.Parent,[Measures].[Internet Order Count])
select {[Measures].[Internet Order Count],[Measures].[Sum of Group],[Measures].[Sum of Top]} on 0
,
Order(Hierarchize({[Top 10 Groups],[Other Groups]}),[Measures].[Internet Order Count],DESC) on 1
from [Adventure Works]
更新-4(以年/月为例的解决方案)
@whytheq的惊人解决方案帮助我做了我想要的事情:
WITH
SET [All Grupa Klientow] AS ([Report Date].[Report Date Y].Children)
SET [All Klient] AS ([Report Date].[Report Date YM].Children)
SET [Top N Members] AS
Generate
(
[All Grupa Klientow]
,TopCount
(
(EXISTING
[All Klient])
,3
,[Measures].[Count]
)
)
MEMBER [Report Date].[Report Date YM].[Other] AS
Aggregate({(EXISTING {[All Klient]} - [Top N Members])})
SELECT
{[Measures].[Count]} ON 0
,{
[All Grupa Klientow]
*
{
[Top N Members]
,[Report Date].[Report Date YM].[Other]
}
} ON 1
FROM [DATA];
图片:
任务已经解决,但请注明不是这个答案,而是@ whytheq's!
答案 1 :(得分:2)
以下是针对AdvWrks
并使用我在Chris Webb博客上看到的技术,他在此概述:
https://cwebbbi.wordpress.com/2007/06/25/advanced-ranking-and-dynamically-generated-named-sets-in-mdx/
创建MyMonthsWithEmployeesSets集的脚本部分我觉得很难理解 - 也许@AlexPeshik可以更多地了解下面脚本中发生的事情。
WITH
SET MyMonths AS
TopPercent
(
[Date].[Calendar].[Month].MEMBERS
,20
,[Measures].[Reseller Sales Amount]
)
SET MyEmployees AS
[Employee].[Employee].[Employee].MEMBERS
SET MyMonthsWithEmployeesSets AS
Generate
(
MyMonths
,Union
(
{[Date].[Calendar].CurrentMember}
,StrToSet
("
Intersect({},
{TopCount(MyEmployees, 10, ([Measures].[Reseller Sales Amount],[Date].[Calendar].CurrentMember))
as EmployeeSet"
+
Cstr(MyMonths.CurrentOrdinal)
+ "})"
)
)
)
MEMBER [Employee].[Employee].[RestOfEmployees] AS
Aggregate
(
Except
(
MyEmployees
,StrToSet
(
"EmployeeSet" + Cstr(Rank([Date].[Calendar].CurrentMember,MyMonths))
)
)
)
MEMBER [Measures].[EmployeeRank] AS
Rank
(
[Employee].[Employee].CurrentMember
,StrToSet
(
"EmployeeSet" + Cstr(Rank([Date].[Calendar].CurrentMember,MyMonths))
)
)
SELECT
{
[Measures].[EmployeeRank]
,[Measures].[Reseller Sales Amount]
} ON 0
,Generate
(
Hierarchize(MyMonthsWithEmployeesSets)
,
[Date].[Calendar].CurrentMember
*
{
Order
(
Filter
(
MyEmployees
,
[Measures].[EmployeeRank] > 0
)
,[Measures].[Reseller Sales Amount]
,BDESC
)
,[Employee].[Employee].[RestOfEmployees]
}
) ON 1
FROM [Adventure Works];
编辑 - Alex第三次尝试的解决方案:
WITH
SET [AllCountries] AS [Country].[Country].MEMBERS
SET [AllStates] AS [State-Province].[State-Province].MEMBERS
SET [Top2States] AS
Generate
(
[AllCountries]
,TopCount
(
(EXISTING
[AllStates])
,3
,[Measures].[Internet Order Count]
)
)
MEMBER [State-Province].[All].[RestOfCountry] AS
Aggregate({(EXISTING {[AllStates]} - [Top2States])})
SELECT
{[Measures].[Internet Order Count]} ON COLUMNS
,{
[AllCountries]
*
{
[Top2States]
,[State-Province].[All].[RestOfCountry]
,[State-Province].[All]
}
} ON ROWS
FROM [Adventure Works];