是否可以编写 "last x days of days of week" 格式的 MDX 查询?
Is it possible to write an MDX query of the format "last x days of days of week"?
这是一份大量手动维护的报告,我正在尝试自动执行 SSAS 多维数据集的位视图。
该报告包含每日销售额,除此之外,还有一个名为 "last 4 's" 的度量。例如,对于 10 月 16 日星期五,衡量指标是过去 4 个星期五的平均销售额。
有没有一种方法可以在 MDX 中以可以放置在 SSAS 多维数据集中的计算度量中的方式构建它?
ps--针对whytheq的问题,是的,日期维度包括星期几,它是一个整数,其中Sun = 1,Mon = 2等等到Sat = 7。
我看我上面说的有点含糊。上面的 "last 4 Fridays" 是指 10 月 16 日之前的 4 个星期五,而不是最近的 4 个星期五。
同意 whytheq,更多信息可能有助于我们创建最佳解决方案。不管怎样:
如果您只有平日层次结构,则已解决:
+All
-2015/01/01
-2015/01/02
...
-2015/12/31
...
逻辑可能是这样的:
全天排名
按周拆分
计算每天类型的最后 4 个
显示每个选定成员的结果
平面层次结构示例[报告日期].[报告日期].[日]计算:
with
member [Measures].[AllDaysRank] as Rank([Report Date].[Report Date].CurrentMember,[Report Date].[Report Date].[Day].Members)
member [Measures].[WeekDay] as ([Measures].[AllDaysRank]-(Int([Measures].[AllDaysRank]/7)*7))
set [Last4Set0] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=0),4,[Measures].[AllDaysRank])
set [Last4Set1] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=1),4,[Measures].[AllDaysRank])
set [Last4Set2] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=2),4,[Measures].[AllDaysRank])
set [Last4Set3] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=3),4,[Measures].[AllDaysRank])
set [Last4Set4] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=4),4,[Measures].[AllDaysRank])
set [Last4Set5] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=5),4,[Measures].[AllDaysRank])
set [Last4Set6] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=6),4,[Measures].[AllDaysRank])
member [Measures].[Last4Measure] as
case [Measures].[WeekDay]
when 0 then sum([Last4Set0],[Measures].[Count])
when 1 then sum([Last4Set1],[Measures].[Count])
when 2 then sum([Last4Set2],[Measures].[Count])
when 3 then sum([Last4Set3],[Measures].[Count])
when 4 then sum([Last4Set4],[Measures].[Count])
when 5 then sum([Last4Set5],[Measures].[Count])
when 6 then sum([Last4Set6],[Measures].[Count])
end
select {[Measures].[Count],[Measures].[AllDaysRank],[Measures].[WeekDay],[Measures].[Last4Measure]} on 0
,[Report Date].[Report Date].[Day].Members on 1
from [DATA]
结果(Count,AllDaysRank,WeekDay,Last4Measure):
20151001 10 740 5 35
20151002 10 741 6 39
20151003 8 742 0 37
20151004 12 743 1 42
20151005 13 744 2 42
20151006 12 745 3 39
20151007 10 746 4 36
20151008 8 747 5 35
20151009 6 748 6 39
20151010 11 749 0 37
20151011 10 750 1 42
20151012 7 751 2 42
20151013 8 752 3 39
20151014 6 753 4 36
20151015 9 754 5 35
20151016 11 755 6 39
20151017 11 756 0 37
20151018 10 757 1 42
20151019 14 758 2 42
20151020 8 759 3 39
20151021 11 760 4 36
20151022 4 761 5 35
20151023 16 762 6 39
20151024 5 763 0 37
20151025 10 764 1 42
20151026 8 765 2 42
20151027 11 766 3 39
20151028 9 767 4 36
20151029 14 768 5 35
20151030 6 769 6 39
20151031 10 770 0 37
如果你有周层次结构或一些属性(不是计算天数),会更容易。
UPDATE(存在每周属性):
这是几周的脚本,但请先创建 weekday->day
层级,例如:
All
+1
-2015/01/01
-2015/01/08
...
+2
-2015/01/02
-2015/01/09
...
代码中有代码技巧,我将进一步解释:
with
member [Measures].[Week Day INFO] as [Report Date].[Week Day].Properties( "Report Date Week Day" )
member [Measures].[Last4Measure] as
/* if there are no empty 4 weeks for the first dates with data, take smaller size */
iif([Report Date].[Week Day].CurrentMember.Lag(3).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,iif([Report Date].[Week Day].CurrentMember.Lag(2).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,iif([Report Date].[Week Day].CurrentMember.Lag(1).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,sum({[Report Date].[Week Day].CurrentMember},[Measures].[Count])
,sum({[Report Date].[Week Day].CurrentMember.Lag(1):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
,sum({[Report Date].[Week Day].CurrentMember.Lag(2):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
/* end of fixing, which could be necessary */
/* calculation part */
,sum({[Report Date].[Week Day].CurrentMember.Lag(3):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
select
{[Measures].[Count],[Measures].[Week Day INFO],[Measures].[Last4Measure]} on 0
,[Report Date].[Report Date].[Day].members on 1
from [DATA]
Week Day INFO
测量仅供查看结果,计算时不需要。
要计算的确切代码非常简单:sum({[Report Date].[Week Day].CurrentMember.Lag(3):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
但是您可能没有空虚或无意义的日子,而这对于此计算是必需的!因为它使用 .lag(3)
,一旦我们尝试计算非常第一、第二或第三周,它将需要前一个工作日的最后一个成员,例如计算有史以来第二个星期三的 .lag(3)(在日期维度的开头),需要第二个星期三、第一个星期三、最后一个星期二、最后一个星期二之前,这是不可接受的,所以我增加了递减延迟- 通过检查父级名称(因为父级是我们已经创建的层次结构中的工作日编号)。
没问题,您将使用 AVG 而不是 SUM。我使用 SUM 来简化检查答案。它是动态的,不仅仅针对最后一个成员。这取决于当前成员。
如果您在日期维度中有一个指示星期几的层次结构,那么您应该在这种问题的情况下使用它。
通过AdvWrks
我写了以下内容:
WITH
MEMBER [Measures].[Avg4wkDays] AS
Sum
(
Tail
( --<<find just the past 4
Exists
( --<< find all the days from the past 25 days which have the same day of the week as the current date
Tail
( --<< find the last 25 days prior to each date
NULL : [Date].[Calendar].CurrentMember
,25
)
,Exists
( --<< find the Day of the Week for the currentmember
[Date].[Day of Week].[Day of Week].MEMBERS
,[Date].[Calendar].CurrentMember
)
)
,4
)
,[Measures].[Internet Sales Amount]
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[Avg4wkDays]
} ON 0
,
[Date].[Calendar].[Date] * [Date].[Day of Week].[Day of Week] ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar Year].&[2007];
给出符合要求的如下:
这是一份大量手动维护的报告,我正在尝试自动执行 SSAS 多维数据集的位视图。
该报告包含每日销售额,除此之外,还有一个名为 "last 4 's" 的度量。例如,对于 10 月 16 日星期五,衡量指标是过去 4 个星期五的平均销售额。
有没有一种方法可以在 MDX 中以可以放置在 SSAS 多维数据集中的计算度量中的方式构建它?
ps--针对whytheq的问题,是的,日期维度包括星期几,它是一个整数,其中Sun = 1,Mon = 2等等到Sat = 7。
我看我上面说的有点含糊。上面的 "last 4 Fridays" 是指 10 月 16 日之前的 4 个星期五,而不是最近的 4 个星期五。
同意 whytheq,更多信息可能有助于我们创建最佳解决方案。不管怎样:
如果您只有平日层次结构,则已解决:
+All
-2015/01/01
-2015/01/02
...
-2015/12/31
...
逻辑可能是这样的:
全天排名
按周拆分
计算每天类型的最后 4 个
显示每个选定成员的结果
平面层次结构示例[报告日期].[报告日期].[日]计算:
with
member [Measures].[AllDaysRank] as Rank([Report Date].[Report Date].CurrentMember,[Report Date].[Report Date].[Day].Members)
member [Measures].[WeekDay] as ([Measures].[AllDaysRank]-(Int([Measures].[AllDaysRank]/7)*7))
set [Last4Set0] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=0),4,[Measures].[AllDaysRank])
set [Last4Set1] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=1),4,[Measures].[AllDaysRank])
set [Last4Set2] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=2),4,[Measures].[AllDaysRank])
set [Last4Set3] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=3),4,[Measures].[AllDaysRank])
set [Last4Set4] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=4),4,[Measures].[AllDaysRank])
set [Last4Set5] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=5),4,[Measures].[AllDaysRank])
set [Last4Set6] as TopCount(Filter([Report Date].[Report Date].[Day].Members,[Measures].[WeekDay]=6),4,[Measures].[AllDaysRank])
member [Measures].[Last4Measure] as
case [Measures].[WeekDay]
when 0 then sum([Last4Set0],[Measures].[Count])
when 1 then sum([Last4Set1],[Measures].[Count])
when 2 then sum([Last4Set2],[Measures].[Count])
when 3 then sum([Last4Set3],[Measures].[Count])
when 4 then sum([Last4Set4],[Measures].[Count])
when 5 then sum([Last4Set5],[Measures].[Count])
when 6 then sum([Last4Set6],[Measures].[Count])
end
select {[Measures].[Count],[Measures].[AllDaysRank],[Measures].[WeekDay],[Measures].[Last4Measure]} on 0
,[Report Date].[Report Date].[Day].Members on 1
from [DATA]
结果(Count,AllDaysRank,WeekDay,Last4Measure):
20151001 10 740 5 35
20151002 10 741 6 39
20151003 8 742 0 37
20151004 12 743 1 42
20151005 13 744 2 42
20151006 12 745 3 39
20151007 10 746 4 36
20151008 8 747 5 35
20151009 6 748 6 39
20151010 11 749 0 37
20151011 10 750 1 42
20151012 7 751 2 42
20151013 8 752 3 39
20151014 6 753 4 36
20151015 9 754 5 35
20151016 11 755 6 39
20151017 11 756 0 37
20151018 10 757 1 42
20151019 14 758 2 42
20151020 8 759 3 39
20151021 11 760 4 36
20151022 4 761 5 35
20151023 16 762 6 39
20151024 5 763 0 37
20151025 10 764 1 42
20151026 8 765 2 42
20151027 11 766 3 39
20151028 9 767 4 36
20151029 14 768 5 35
20151030 6 769 6 39
20151031 10 770 0 37
如果你有周层次结构或一些属性(不是计算天数),会更容易。
UPDATE(存在每周属性):
这是几周的脚本,但请先创建 weekday->day
层级,例如:
All
+1
-2015/01/01
-2015/01/08
...
+2
-2015/01/02
-2015/01/09
...
代码中有代码技巧,我将进一步解释:
with
member [Measures].[Week Day INFO] as [Report Date].[Week Day].Properties( "Report Date Week Day" )
member [Measures].[Last4Measure] as
/* if there are no empty 4 weeks for the first dates with data, take smaller size */
iif([Report Date].[Week Day].CurrentMember.Lag(3).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,iif([Report Date].[Week Day].CurrentMember.Lag(2).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,iif([Report Date].[Week Day].CurrentMember.Lag(1).Parent.Member_Key <> [Report Date].[Week Day].CurrentMember.Parent.Member_Key
,sum({[Report Date].[Week Day].CurrentMember},[Measures].[Count])
,sum({[Report Date].[Week Day].CurrentMember.Lag(1):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
,sum({[Report Date].[Week Day].CurrentMember.Lag(2):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
/* end of fixing, which could be necessary */
/* calculation part */
,sum({[Report Date].[Week Day].CurrentMember.Lag(3):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
select
{[Measures].[Count],[Measures].[Week Day INFO],[Measures].[Last4Measure]} on 0
,[Report Date].[Report Date].[Day].members on 1
from [DATA]
Week Day INFO
测量仅供查看结果,计算时不需要。
要计算的确切代码非常简单:sum({[Report Date].[Week Day].CurrentMember.Lag(3):[Report Date].[Week Day].CurrentMember},[Measures].[Count]))
但是您可能没有空虚或无意义的日子,而这对于此计算是必需的!因为它使用 .lag(3)
,一旦我们尝试计算非常第一、第二或第三周,它将需要前一个工作日的最后一个成员,例如计算有史以来第二个星期三的 .lag(3)(在日期维度的开头),需要第二个星期三、第一个星期三、最后一个星期二、最后一个星期二之前,这是不可接受的,所以我增加了递减延迟- 通过检查父级名称(因为父级是我们已经创建的层次结构中的工作日编号)。
没问题,您将使用 AVG 而不是 SUM。我使用 SUM 来简化检查答案。它是动态的,不仅仅针对最后一个成员。这取决于当前成员。
如果您在日期维度中有一个指示星期几的层次结构,那么您应该在这种问题的情况下使用它。
通过AdvWrks
我写了以下内容:
WITH
MEMBER [Measures].[Avg4wkDays] AS
Sum
(
Tail
( --<<find just the past 4
Exists
( --<< find all the days from the past 25 days which have the same day of the week as the current date
Tail
( --<< find the last 25 days prior to each date
NULL : [Date].[Calendar].CurrentMember
,25
)
,Exists
( --<< find the Day of the Week for the currentmember
[Date].[Day of Week].[Day of Week].MEMBERS
,[Date].[Calendar].CurrentMember
)
)
,4
)
,[Measures].[Internet Sales Amount]
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[Avg4wkDays]
} ON 0
,
[Date].[Calendar].[Date] * [Date].[Day of Week].[Day of Week] ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar Year].&[2007];
给出符合要求的如下: