数据分析表达式 (DAX) 语言是一种公式语言,Data Analysis Expressions 数据分析表达式,简称DAX表达式,其允许用户定义自定义计算。DAX 包含一些在 Excel 公式中使用的函数,此外还包含其他设计用于处理关系数据和执行动态聚合的函数。
DAX 公式与 Excel 公式非常相似,要创建 DAX 公式,请键入一个等号,后跟函数名或表达式以及所需的任何值或参数,DAX支持常见的4中运算符:算数运算符(+、-、*、/、^)、比较运算符(=、>、<、<=、>=、<>)、文本运算符(&)、逻辑运算符(&&、||)。
除了以上运算符外,DAX 提供多种函数,与 Excel 类似,可用于处理字符串、使用日期和时间执行计算或者创建条件值,像SUM求和函数,这种函数数据量非常多,超过200个,但是常用的函数有几类:日期和时间函数、时间智能函数、统计函数,后续我们会一一学习。
DAX表达式的格式如下:
销售额=SUM(表1[列1])
即:所有的公式必须引用表名,先指定表名再指定列名。
度量值是通过DAX表达式创建的一个虚拟的数据值,其不改变源数据,不改变数据模型,在Power BI图表中通过度量值可以快速便捷的统计一些我们想要的指标。
新建度量值有三种途径分别为"模型"视图中的新建度量值、"报表"视图中的新建度量值以及在"字段"区域鼠标右键新建度量值,三者的新建度量值是一样的,可见新建度量值的重要程度。
通过以上三种方式都可以新建度量值,下面在"模型"中选中门店信息表,点击"新建度量值"
在弹出的界面中输入:总营业额 = SUM('门店信息'[月营业额]) ,以上公式就是DAX公式,编写完成后回车或者点击前面的"√"完成编辑,可以在字段中对应的"门店信息"表中看到新增的"总营业额"指标,该字段不会在表中展示,只是一个虚拟的指标列。
新建的度量值功能非常强大,例如我们要统计每个省份、城市、区县的总营业额,可以通过度量值来快速实现。
统计每个省份中营业额
统计每个区县总营业额
通过以上操作我们可以看到只需要操作对应的行值,相应的总营业额就能自动统计出来,非常方便。此外,如果我们在Power BI中设置了"分片器",随着分片器的设置不同,对应的"总营业额"度量值也会变化。
快度量值相当于度量值的简化版,不需要手写度量值DAX公式,其提供了一些简单的运算供我们选择,不灵活,建议多使用新建度量值。下面演示快度量值的操作。
假设我们现在需要统计门店信息中每种商圈类型的平均租金,可以通过快度量值来完成,操作如下:
可见以上创建的"快度量值"默认创建在了第一张"区县信息"表下,如果不想创建在该表下,可以在对应的表中右键选择"新建快速度量值"来完成,如上图所示。
下面我们可以通过创建"卡片图"可视化来展示商圈类别对应的平均租金,操作如下:
上图中展示的平均值有百万单位,我们也可以将单位去掉或者改成其他单位,操作如下:
最终效果如下:
注意以上结果显示的是11个商圈种类下平均租金,也可以选择不同的商圈类型查看每个商圈的均值,也是各个商圈的总值。
如果我们要使用的列不在数据表中,可以通过新建列来利用已有的字段生成需要的字段列。通过这种方式添加的字段会添加到已有的数据表中,这里的新建列与前面导入数据后新建列一样。
例如:根据门店信息表中的销售额对门店进行分类:高营收、中营收、底营收三档,操作如下:
首先打开"图表"视图,选择对应的"门店信息表",查看月营业额范围为80000-250000之间。
"新建列"操作,设置DAX公式来配置营收分档:营收分档 = IF('门店信息'[月营业额]<150000,"低营收",IF('门店信息'[月营业额]<200000,"中营收","高营收"))
为了更清晰的了解营收情况,我们可以绘制条形图来观察营收分档的数据:
DAX中新建表与新建列一样,也是利用已有的数据表通过DAX表达式生成所需的表格。常见的新建表有创建维度表、创建交叉联合表、创建纵向合并表,下面一一进行讲解。
通常维度表都是由外部数据导入到Power BI中,一些情况下我们也可以根据已有的事实表进行提取维度数据形成维度表,即将表中的某一列数据进行去重提取数据存入一张表形成维度数据。例如在"门店信息表"中我们可以观察每条数据都对应一个门店类型,那么可以针对门店类型列进行去重处理得到门店类型的维度数据形成维度表。
以上针对事实表中某列进行去重提取数据形成维度表可以通过DAX公式实现,有两种方式分别为VALUES()和DISTINCT()。
VALUES(表[列]):返回的是该列唯一值的新表。
VALUES(表):复制原表。
DISTINCT(表[列]):返回含有该列唯一值的新表,与VALUES(表[列])用法一致。
DISTINCT(表):返回具有不重复行的新表。
DISTINCT(表的表达式):针对表的表达式返回该表具有不重复行的新表。
以上VALUES()和DISTINCT()表达式各有个的用途,DISTINCT()不仅可以获取某列的唯一值形成新表,还可以对表中数据去重得到新表,所以DISTINCT()使用相对较多。
需求:针对"门店信息"表中门店类型进行提取维度数据,具体操作如下:
点击"新建表"之后输入DAX表达式:门店类型表 = DISTINCT('门店信息'[门店类型]),如下:
同样也可以使用VALUES()函数来实现,同样选择"新建表",输入表达式:门店类型表2 = VALUES('门店信息'[门店类型])
以上使用VALUES和DISTINCT函数表达式来得到的结果都是一样的。
交叉联合表就是按照两张表中相同字段进行匹配,横向合并在一起,实现交叉联合表就需要使用NATURALINNERJOIN()函数,该函数使用方式如下:
NATURALINNERJOIN(LeftTable,RightTable)
以上左表和右表要求必须有相同的关联列,并且建立了模型关系,通过NATURALINNERJOIN函数会返回两表所有列字段组成的新表,否则会出错。
需求:针对"门店信息"表与"区县信息"表构建交叉联合表,之前我们已经针对两表建立了模型关系:
所以可以直接进行构建交叉联合表,"新建表"之后可以输入DAX表达式:交叉联合表 = NATURALINNERJOIN('门店信息',VALUES('区县信息'[区县名称]))
注意:在使用NATURALINNERJOIN时不允许表中有与左表相同的列,所以这里我们使用VALUES('区县信息'[区县名称])筛选出对应的列即可。也可以嵌套NATURALINNERJOIN来获取其他表中更多的数据列,例如我们可以针对这个结果关联"城市信息"将城市信息也展示在交叉联合表中,DAX表达式如下:
两表形成纵向合并表就是将一张表追加到另外一张表中,类似与Power Query中表的追加效果一样。我们可以通过UNION函数来实现多张表的纵向合并,但是要求这些表必须有相同的列结构,否则不能追加合并或者合并之后的数据有缺失。
现有2022年第一到第四季度的点播订单表,基于四个季度的订单表创建纵向合并表。首先按照之前方式导入四个季度的数据:
然后通过UNION DAX公式创建纵向合并表,公式如下:2022年点播订单表 = UNION('第一季度点播订单表','第二季度点播订单表','第三季度点播订单表','第四季度点播订单表')
在Power BI中我们经常使用时间函数来对包含日期列的数据表进行时间转换操作做进一步的分析,这里我们通过Power BI创建一张日期表来演示日期函数的操作使用。
在Power BI中创建日期表常见的有两种函数:CALENDAR和ADDCOLUMNS。下面分别介绍。
创建日期表可以使用CALENDAR函数来实现,其用法如下:
CALENDAR(StartDate,EndData)
CALENDAR函数可以通过指定一个开始日期和结束日期生成一列顺序的日期数据表。在Power BI中"新建表"输入以下DAX公式:日期测试表 = CALENDAR(DATE(2022,01,01),DATE(2022,12,31)),生成日期表:
以上日期表生成之后,我们可以"新建列"根据当前列通过DAX函数来抽取日期列的年、月、日等信息,操作如下,新建列并指定DAX表达式为:年份 = YEAR([DATE])
按照以上方式我们多次创建列并输入DAX表达式:月份 = MONTH([DATE]),日期 = DAY([DATE]),如下:
可以看到,如果有非常多的列要一次性添加,每次都需要"新建列"操作,如果我们还要基于源字段来创建更多的列,例如:"季度"、"星期",为了方便我们可以直接通过ADDCOLUMNS函数来一次性创建多个列的日期表。
ADDCOLUMNS函数作用是用来向指定表添加列并返回具有新列的表,其用法如下:
ADDCOLUMNS(表,"名称1","表达式1","名称2","表达式2"...)
以上表是指向哪个表中添加列,后续的名称1是要添加的列名称,紧跟的表达式是获取该列值对应的DAX表达式,如果有多个新增的列以此类推往后写多个名称和表达式。
需求:创建一张时间表,包含年份、月份、日期、季度、星期、年份季度、年月、年周、全日期列字段,具体操作如下,新建表,输入DAX公式如下:
日期表2 = ADDCOLUMNS(
CALENDAR(DATE(2022,01,01),DATE(2022,12,31)),
"年份",YEAR([Date]),
"月份",MONTH([Date]),
"日期",DAY([Date]),
"季度",QUARTER([Date]),
"星期",FORMAT([Date],"AAA"),
"星期2","周"&WEEKDAY([Date],2),
"年份季度",FORMAT([Date],"第Q季度"),
"年月",FORMAT([Date],"YYYY-MM"),
"年周",FORMAT([Date],"YYYY")&"年第"&WEEKNUM([Date],2)&"周",
"全日期",FORMAT([Date],"Long Date")
)
以上通过"&"符号可以连接多个结果;FORMAT是格式化函数,在Power BI中FORMAT格式化的格式还有很多,可以参照下图,根据实际情况来使用。
以上获取日期数据表我们都是自己生成数据来操作的,针对导入到Power BI中含有日期字段的数据表我们也可以根据以上DAX表达式来生成对应的日期各列数据,这就是针对用户的数据构建的动态日期表。
下面我们针对2022年点播订单表来生成对应的动态日期数据,首先新建表,写入DAX表达式:
动态日期表 = ADDCOLUMNS(
CALENDAR(FIRSTDATE('2022年点播订单表'[消费日期]),LASTDATE('2022年点播订单表'[消费日期])),
"年份",YEAR([Date]),
"月份",MONTH([Date]),
"日期",DAY([Date]),
"季度",QUARTER([Date]),
"星期",FORMAT([Date],"AAA"),
"年份季度",FORMAT([Date],"第Q季度"),
"年月",FORMAT([Date],"YYYY-MM"),
"年周",FORMAT([Date],"YYYY")&"年第"&WEEKNUM([Date],2)&"周",
"全日期",FORMAT([Date],"Long Date")
)
注意:以上创建日期数据与之前创建日期数据不同点在于动态日期表中日期是从用户表中获取的,写法为: CALENDAR(FIRSTDATE('2022年点播订单表'[消费日期]),LASTDATE('2022年点播订单表'[消费日期])),FIRSTDATE指定开始日期,LASTDATE指定结束日期。
以上针对用户表生成动态日期表后,为了方便后续我们使用,可以在模型关系中与对应的用户表创建模型关系:
我们可以通过SELECTCOLUMNS()函数来基于某张表来创建一张新表,SELECTCOLUMNS函数与ADDCOLUMNS函数用法类似,但也有不同,ADDCOLUMNS是针对一张表来添加列,SELECTCOLUMNS是基于一张表来创建新的列而不是基于原表添加列,其使用方式如下:
SELECTCOLUMNS(表,"名称1","表达式1","名称2","表达式2"...)
以上表代表从哪个表选择列,名称1是创建新列的名称,紧跟的表达式1是获取该列值对应的DAX表达式,如果有多个新增的列以此类推往后写多个名称和表达式。
在使用SELECTCOLUMNS函数时经常会涉及到从其他相关联的表中获取数据,需要使用RELATED函数来从更多的表中获取列数据,RELATED函数需要传入一个列名作为参数,作用是查询表中包含的列值,从其他表返回这个列值,要求RELATED查询数据的表必须与SELECTCOLUMNS查询数据的表建立模型关系,否则会报错。
需求:根据导入到Power BI中的"2022年点播订单表"和"门店信息表"数据展示每个门店对应的点播订单信息。
首先我们在"模型"视图中构建两表的模型关系:
然后点击创建表,输入以下DAX公式:
2022门店点播订单信息 = SELECTCOLUMNS(
'2022年点播订单表',
"销售日期",'2022年点播订单表'[消费日期],
"消费时间",'2022年点播订单表'[消费时间],
"消费门店",RELATED('门店信息'[门店名称]),
"点播套餐",'2022年点播订单表'[套餐名称],
"订单金额",('2022年点播订单表'[套餐价格]-'2022年点播订单表'[优惠金额])
)
通过以上操作我们发现销售日期和消费时间列不是我们想要的结构,我们还可以进一步通过"列工具"调整对应的时间格式,操作如下,打开"列工具",选中对应的时间列进行时间格式调整: