本书将时间函数单独作为一节重点介绍,是因为时间维度在商业分析中具有非常特殊的作用。
2.3.1 Tableau的时间函数
Tableau中的日期类型总共分为两种:离散型与连续型,如图2.3.1所示。其中离散型日期胶囊为蓝色,连续型日期胶囊为绿色。
图2.3.1
图2.3.2所示的为两种日期类型的对比结果。显然,离散型日期更适用于柱形图,而连续型日期更适用于类似折线图等连续型可视化图。单击日期胶囊中的加号按钮,可对日期进行下钻至季、月、周、日等,包括“精确日期”。
用鼠标右击选中维度区中的【订单日期】胶囊,将其拖曳至工作表【行】中,界面中会弹出【放置字段】对话框,如图2.3.3所示。对话框中有两组类似的日期单位,上方为离散型日期单位,下方为连续型日期单位。其中符号“ ”代表离散型日期单位、“ ”代表连续型日期单位。
图2.3.2
图2.3.3
Tableau中提供了多种日期函数,表2.3.1中列举了主要函数的功能。
表2.3.1
需要注意的是,用鼠标右击【订单日期】胶囊,在弹出的快捷菜单中选择【创建】→【自定义日期】命令,如图2.3.4所示。在打开的对话框中可快速(无公式)创建【订单日期(季度)】计算字段,如图2.3.5所示,其功能等同于公式 DATEPART('quarter',[订单日期])。
图2.3.4
图2.3.5
在Tableau模型中,不建议创建独立的日期维度表,大部分的时间计算都可以直接通过Tableau的日期函数完成。
2.3.2 Power BI中的时间函数
1.时间日期表
在Power BI模型中,大多数时候都需要创建专有的日期表,尤其是在多表中都有日期字段时,统一专有的日期表十分必要。在创建日期表时,日期字段需要满足以下条件:
· 包含唯一值(1表要求);
· 不包含任何空值;
· 包含连续的日期值(从开头到结尾);
· 如果是日期/时间数据类型,则每个值都要具有相同的时间戳(比如都是 00:00 或者12:00)。
下面的公式为简单的日期表创建公式。此公式是以订单日期的最小值和最大值为依据的时间范围且返回【Date】字段。然后用户可以通过DAX公式,依据【Date】字段,创建更多自定义的日期字段。若需要更丰富的日期字段,则可在Power BI中创建新表,输入以下公式,效果如图2.3.6所示。
以上公式是在原有的简单日期表的基础上通过GENERATE函数产生的相关日期字段。
图2.3.6
注意,【日期键】字段的数据类型为文本字符串,在遇到订单日期为日期+时间的形式时,此字段无法直接与【Date】关联,原因是部分时间无法匹配。在这种情况下需要在两张表中分别创建【日期键】字段,完成关联。
2.标记为日期表
通过Power BI的菜单可将【Date】字段标记为日期表,如图2.3.7所示。
图2.3.7
微软官方对标记为日期表功能给出了以下提醒和建议:
请务必注意,用户在指定自己的日期表时,Power BI Desktop 不会自动创建将代表用户构建到模型中的层次结构。在Power BI Desktop 中,如果取消选择日期表(并且不再具有手动设置的日期表),则Power BI Desktop 将针对表中的日期列为用户重新自动创建内置日期表。
另请务必注意,在将表标记为日期表时,将删除 Power BI Desktop 创建的内置(自动创建的)日期表,并且之前基于这些内置表创建的任何视觉对象或 DAX 表达式将不再正常工作。
在实际使用中,只要创建了图2.3.6所示的日期表(如上例子),并产生了有效的表关联,标记为日期表就不是必要的了。
3.时间智能函数
DAX日期函数大致分为两种。
(1)普通日期函数
普通日期函数有CALENDAR、CALENDARAUTO、DATEDIFF、WEEKNUM、EDATE、EOMONTH等。
(2)时间智能函数
时间智能函数是指对输入值带有日期识别功能的函数,通过使用时间智能函数确定日期范围,再结合聚合函数和CALCULATE函数就可以进行各种时间的比较计算。表2.3.1中列出一部分主要的时间智能函数。
表2.3.1
注意: 时间智能函数参数必须使用日期表中的日期键才生效。
回到上例的日期表中,依据表2.3.2所示的公式创建新日期字段。
表2.3.2
表2.3.2所示的为DAX计算列公式,其中频繁使用到了ALL、EARLIER、FILTER、COUNTROWS等函数。最让人困惑的EARLIER函数,用于需要将当前行与自身列的其他单元格相比较的情况。DAX中没有单元格的概念,必须借助EARLIER函数(在旧版本中被称为OUTER函数)返回相同“列”中的其他单元格作为当前行值,再与自身列进行对比。
比如,在'Date'[Date]<=EARLIER ('Date'[Date])中,EARLIER是参照列,与'Date'[Date]相比,对第一行“20050101”来说,其逻辑为:'Date'[Date]<='20150101',小于或等于它的值只有它自己,因此通过COUNTROWS函数计算返回结果“1”。
笔者理解该逻辑的口诀为:“Eariler,即OUTER,对比全,返当前”。