最近工作有点忙。过年最后一天都在奋战。真真是一天酱油都没打。有强迫症,天天关一堆Devops上的case也挺有成就感的。6个字原则。
今年也要学习新东西,感觉我这样的人想学什么应该都很快的吧。

海贼王里,各种各样的海贼团。每个海贼团都有自己的船。其中路飞从最开始的小木桶,后来的黄金梅利号,到现在的万里阳光号。不同的船大概航行了多久呢?在不同日期选择下,船只的航行时间如何呢?各种气体排放量,燃料利用率怎么样呢?先搞个航行时间这个简单的来试一下吧。

需求:
1. 展示需求:对于Power BI需要展示的报表来说,要有一个关于Date时间的切片器Slicer,可以选择不同的年份Year,月份Year Month和日期Date。对于不用的船Vessel Name,也可以做切片来考察不同的船的航行时间。所以也要有一个船Vessel Name的切片器slicer。页面展示的Visualization就简单的有一个Card来展示下总的航行时间Operational Days就可以了。
2. 数据需求:
如果默认没有选择任何的日期,则按照当天来计算当月的航行时间;如果选择了,则按照选择计算的时间来计算航行时间;
如果航行开始时间operation_start_date,小于选择了的时间,则按照选择时间开始计算;如果航行开始时间operation_end_date为空或者大于选择了的时间,则用选择了的时间算作航行结束时间。
时间计算基于每一条船来计算。
数据准备:
一张Dim_Date的时间维度表,包括年,年月,日字段;
一张Dim_Vessel的包括各种船的维度信息表,至少包括船的ID,名字已经航行开始和航行结束时间;
一张Fact事实表,里面包含了时间,燃料消耗情况,各种气体排放情况等等的事实信息表。在本例子里,这个Fact表是一个工具表,只是为了连结Dim_Date和Dim_Vessel来存在,所以只包括几个简单的字段,FK_Vessel,FK_Date,PK_Fact。
建立模型:本例中就三张表。PK和FK之间互相链接。单独建立了一张Measures -Table来放所有的度量信息。

分析:数据方面,对于逻辑需求清楚的,哪怕需求很多很复杂,只要用户提的出来,基本都可以做,除非...
对于这个计算字段,主要有两个基本点。
1, 要获取筛选信息,根据选择的时间和航行时间来比较;
2, 计算的粒度在row level
本来粒度在row level用Calculated Column挺好的。但是Calculated Column不能对Slicer正确接收。所以就只用万能的Measures了。
创建operational days度量
operational days =
var MaxDate = IF(ISFILTERED(Dim_Date[Date]) || ISFILTERED(Dim_Date[Year Month]) || ISFILTERED(Dim_Date[Year]),MAX(Dim_Date[Date]) ,TODAY())
var MinDate = IF(ISFILTERED(Dim_Date[Date]) || ISFILTERED(Dim_Date[Year Month]) || ISFILTERED(Dim_Date[Year]), MIN(Dim_Date[Date]), DATE(YEAR(TODAY()),1,1))
VAr tt = SUMX(SUMMARIZE(Dim_Vessel,Dim_Vessel[pk_vessel_details],Dim_Vessel[operation_end_date],Dim_Vessel[operation_start_date],"nn",
VAr n1_end = MAX(Dim_Vessel[operation_end_date])
VAr n1_st = MIN(Dim_Vessel[operation_start_date])
VAR nw_st = IF(n1_st < MinDate,MinDate, IF(AND(n1_st>=MinDate,n1_st<= MaxDate),n1_st,BLANK()))
var nw_end = IF(ISBLANK(n1_end),MaxDate,IF(n1_end >=MaxDate,MaxDate,IF(AND(n1_end>MinDate,n1_end<MaxDate),n1_end,MinDate)))
VAr diff = DATEDIFF(nw_st,nw_end,DAY)
return diff),[nn])
return tt
创建报表如下图所示

当没有选择任何Date Filter的时候,校验数据可以看到,Operation_start_date是2017年5月23,Operation_end_date是空,根据逻辑计算Operation_start_date用的是2021年1月1日,operation_end_date用的是2021年3月18日(今天),结果正确。
如果选择了2021年的1,2,3月。结果是89天。

选择了整个2020年检查了一下,目测目前的逻辑都是对的。

好像也挺简单的。其实也也是可以有改进的地方。比如,当operation_end_date如果是空的话,返回今天
var nw_end = IF(ISBLANK(n1_end),Today(),IF(n1_end >=MaxDate,MaxDate,IF(AND(n1_end>MinDate,n1_end<MaxDate),n1_end,MinDate)))
具体问题具体分析吧。不过基本方法就是在函数里面嵌套变量。

谢谢关注!又是一起加油的一天吖
