求教最近发货日期和平均发货周期的MDX写法的问题

0
请问如下问题如何通过计算成员实现?
比如有客户发货交易记录作为事实表,度量值为发货量,与客户、时间维度组成Cube。
发货量在按客户和月份统计,这个很好办。

但是我现在是否能够设置计算成员,得到每客户,每月的最近一次发货日期以及每月的平均发货周期(也就是当月每笔发货交易记录与“上一次”发货记录之间的间隔天数的平均值)。
当然这里所说的“上一次”其实是根据分析时的维度组合变化的。比如按(客户,产品)维度组合看的时候,那么在每一笔发货记录匹配上一次发货日期时需要考虑匹配客户和产品字段;如果按(客户)维度组合看的时候,就只需要匹配客户一个字段了。

所以呢,根据上面的描述,每一笔发货记录对应的上一次发货日期是根据分析时的维度组合变化的,因此这个信息肯定就不能在ETL过程中去计算。所以我想应该只能放在cube中通过计算成员来计算。但是苦于刚开始学BI,一些概念和MDX不是很熟练,MDX倒腾了半天,没写出来。。。。惭愧,求赐教,多谢。
已邀请:
3

never515 - 产品规划师/产品经理 2013-11-07 回答

首先需要先确认几个问题
第一:每月平均发货周期这个计算量值的实际计算方法:
有两种可能性,请说明是哪一种:
Ⅰ、在当前未完成月的每月平均发货周期计算方法是:从当月第一天截止到当前天每一次发货的间隔天数之和/从当月第一天起到当前天的总的发货次数;之前已完成月份的每月平均发货周期的计算方法是:该月总天数/该月总的发货次数。
Ⅱ、无论是否为当前月,所有月份的每月平均发货周期计算方法是:该月份每笔发货交易记录与“上一次”发货记录之间的间隔天数之和/截止到某天该月发货次数。
第二:间隔天数的实际计算方法,有两种个可能:
Ⅰ、间隔天数=每笔发货日期-前一次发货日期
Ⅱ、间隔天数=每笔发货日期-前一次发货日期-1【这种是实际间隔数,间隔两边实际发货的那两天都不计算在内,比如是1号到30号实际间隔数为28天=30(总天数)-1(1号这一天)-1(30号这一天)】
第三:每月头尾都没有发货的情况下,间隔天数的计算方法,有两种可能:
Ⅰ、实际没有发货则不计算入间隔天数中
Ⅱ、每月头尾即使没有发货也需要计算间隔天数

就以上问题举一个例子:
当前日期为2013年11月6日,取之前的两个已完成月(2013年9月与2013年10月)与当前未完成月(2013年11月)三个月份来说明不同计算方法导致不同的结果。
供应商A假设9月份和10月份都发了10次货。
9月份的发货日期为:1,4,6,9,13,17,22,27,28,30
10月份的发货日期为:4,7,11,14,16,17,22,25,27,29
11月的发货日期为:2,3,6
首先看第二个问题,拿9月份(共30天)的演示数据
Ⅰ、第一种计算方法,间隔天数=3 2 3 4 4 5 5 1 2=29
Ⅱ、第二种计算方法:间隔天数=2 1 2 3 3 4 4 0 1=20

然后看第三个问题,拿10月份(共31天)的演示数据,并且按照第二个问题的第二种计算方法计算
Ⅰ、第一种,2 3 2 1 0 4 2 1 1=16
Ⅱ、第二种,(3) 2 3 2 1 0 3 2 1 1 (2)=21
如果另外一个供应商B在10月份同样发了10次货,但是他的发货日期为:1,7,11,14,16,17,22,25,27,31。同样按照第二个问题第二种计算方法计算,供应商B的发货间隔天数之和为:5 3 2 1 0 4 2 1 3=21
从业务上来说,两个供应商A和B,如果在10月份同样发了10次货,那他们的平均发货周期分别为1.6【16(间隔天数之和)/10(发货总次数)】与2.1【21(间隔天数之和)/10(发货总次数)】显然是不太可能,因此第三个问题的计算方式需要是第二种,也就是“每月头尾即使没有发货也需要计算到间隔天数中

然后再回到第二个问题,其实第一种计算方法得到的结果永远是
29(一月30天),30(一月31天),27(二月份28天),28(二月份29天)这四种可能,其实就是每月最后一天-每月1号
第二种计算方法得到的结果永远是该月总天数-该月总发货次数,原因(10月份的演示数据):
对于发货不在月份头尾的情况30(月份总天数)-12(取走12个点,包括10个发货日以及2个月份头尾) 2(因为月份头尾没有发货,需要加回来)=20;
对于发货恰好在头尾的情况30(月份总天数)-10(取走10个发货日)=20

第二个问题也解决了,那么第一个问题:
如果你们实际业务中间隔天数的计算方法是“每笔发货日期-前一次发货日期”,那已完成月份的平均发货周期其实计算方法差别在是该月总天数/该月总的发货次数还是(该月总天数-1)/该月总的发货次数,两者差别不大
如果实际业务中间隔天数的计算方法是“每笔发货日期-前一次发货日期-1”,那对于已完成月份的平均发货周期的两种方法得到的结果会有很大差别。

此处只给出问题一使用方法Ⅰ,问题二使用方法Ⅰ需要的MDX写法


WITH MEMBER . AS --当前实际的具体时间,今天是 2013-11-7 13:46:12
'NOW()'
MEMBER . AS --当前日,按照实际具体日期,这里为7
'DAY(.)'
MEMBER . AS --当前月份,这里为11
'MONTH(.)'
MEMBER . AS --当前年份,这里为2013
'YEAR(.)'
MEMBER . AS --当前的年月,如果月份<10,需要在该月份之前拼接字符0。如果现在时刻为2013年7月,则为201307;如果为2013年11月,则为201311
CASE WHEN . <10
THEN LTRIM(.)+'0'+LTRIM(.)
ELSE LTRIM(.)+LTRIM(.)
END
MEMBER . AS --这里是currentmember的年月,为了与实际年月比较
LEFT(LTRIM(..CurrentMember.MEMBERVALUE),6)
MEMBER . AS --这里是将天数累加,1号记1,2号记2,……30号记30,31号记31
sum(PeriodsToDate(..,..CurrentMember),1)
MEMBER . AS --这里目的是将月和日层次上每个点都赋值为该月总天数
CASE WHEN ..CurrentMember.level.name="Date Key"
THEN (..currentmember.parent.lastchild,.)
WHEN ..CurrentMember.level.name="Month"
THEN ..currentmember.lastchild.value
END
MEMBER . AS --这里求实际间隔天数,按照第一个问题的方法Ⅰ,第二个问题的方法Ⅰ取值。如果是已完成月(2013年11月之前的所有月份),则取当月总天数;如果是未完成月(2013年11月),按照之前文字分析的方法取当前日-1.对于2013年11月7日,就是7-1=6
CASE WHEN .<.
THEN .
WHEN .=.
THEN .-1
END
MEMBER . AS --这里是累计发货次数,当月第一次发货记1,第二次发货记2,发了10次货,那么在第十次发货那一天记10
sum(PeriodsToDate(..,..CurrentMember),iif(.>0,1,0))
MEMBER . AS --这里是截止到currentmember为止当月发货次数的和
(..currentmember.lastchild,.)
MEMBER . AS --这里是实际发货次数,按照第一个问题的方法Ⅰ,第二个问题的方法Ⅰ取值。如果是已完成月(2013年11月之前的所有月份),则取当月总的发货次数;如果是未完成月(2013年11月),按照之前文字分析的方法取截止到当天的发货次数和.对于2013年11月7日,截止到7号该月的发货次数和
CASE
WHEN .<.
THEN
CASE
WHEN ..currentmember.level.name="Date Key"
THEN (..currentmember.parent.lastchild,.)
WHEN ..currentmember.level.name="Month"
THEN .
END
WHEN .=.
THEN
CASE
WHEN ..currentmember.level.name="Date Key"
THEN .
WHEN ..currentmember.level.name="Month"
THEN .
END
END
MEMBER . AS --这里是平均发货周期,必须注意.<>0
CASE WHEN .<>0
THEN ./.
END

SELECT (..MEMBERS,.) ON 0,
(..) on 1
FROM
where (...&:...&)



例子中为了书写方便,取的.量值,需要替换为你们业务中的发货量。并且行轴直接取客户和商品的笛卡尔积会非常影响效率。

要回复问题请先登录注册