VAR是DAX中有一个特殊的函数,它的作用是将某个函数的结果存储成为一个参数,供其他函数使用。使用VAR函数可以在很大程度上简化复杂函数的书写过程,提高函数的可读性。同时VAR函数本身的输出结果仅仅与其内部使用的函数有关,不会受到调用它的函数的上下文关系所影响,这就使得用VAR函数定义的参数具有固定性,可以被当做是普通的计算列类型参数所使用。
VAR函数的使用方法如下:
VAR <name> = <expression>
name处定义变量名,要求格式为:
- 支持英文字母和数字组合,但是不能以数字开头。
- 除了可以使用双下划线“__”作为前缀以为,不支持使用其他的特殊字符,包括空格。
- 不能跟内置函数名重复;
不能跟已存在的表同名,但是可以跟原始列重名。
expression处填写用来生成变量值的函数。
VAR函数通常和RETURN关键字一起使用。RETURN后面可以定义一组函数表达式,该表达式当中可以将前面VAR的结果作为参数使用,这样就可以实现将复杂函数进行简化书写。
举个例子来看VAR函数的使用。一般在做Project统计时都涉及到指定milestone时间表,例如下图所示。
假设在同一项目中,每一个milestone的起始时间都是上一个milestone的结束时间。为了获取相同ProjectID下紧邻当前milestone最先结束的milestone时间,需要先根据Project ID进行分组,然后对组内数据进行排序,再之后提取前一个milestone的FinishTime。为了实现该需求,我们可以创建一个度量值调用下面表达式,获取当前表中的每个milestone的起始时间。
StartTime =
VAR MilestoneDate =
MAX ( Project[FinishTime] )
VAR ProjectID =
MAX ( Project[ProjectID] )
RETURN
MAXX (
FILTER (
ALL ( Project ),
Project[FinishTIme] < MilestoneDate
&& Project[ProjectID] = ProjectID
),
Project[FinishTime]
)
在这个表达式中,度量值的名称叫做StartTime;里面有两个VAR函数定义的参数:第一个叫MilestoneDate,一个叫ProjectID。他们的目的是分别获取最大的FinishTime和最大的ProjectID。
在RETURN部分使用了MAXX函数,它可以对表中每一行的表达式进行计算,然后获取结果中的最大数值。MAXX里面调用了FILTER函数,他的目的是生成一个子表单,然后获取当前字表中的最大FinishTime值。 生成子表单的条件是针对Project表中所有数据,取当前FinishTime小于最大FinishTime最大值并且ProjectID=ProjectID最大值。
咦?这个函数看起来都是取最大值的,跟排序没什么关系,那是如何实现需求的呢?秘密就在于当前公式使用了度量值作为载体。度量值的特点是它是一个聚合函数,并且它会根据用户的选择动态的进行聚合计算。当我们用这个公式创建下面这个表单时,度量值StartTime会根据ProjectID,Milestone以及FinishTime这三个关联的上下文进行计算。
将第1行的ProjectID,Milestone以及FinishTime三个数值待入公式可以获得如下结果
函数 | 说明 | 结果 |
---|---|---|
MilestoneDate = MAX ( Project[FinishTime] ) | 受到ProjectID和Milestone这两个上下文影响,相当于找ProjectID=1和Milestone=Milestone A的所有数据,然后获得最大的FinishTime值 | 2/9/2015 (只有当前行数据满足条件) |
ProjectID = MAX ( Project[ProjectID] ) | 同MilestoneDate | 1 |
FILTER ( ALL ( Project ), Project[FinishTime] < MilestoneDate && Project[ProjectID] = ProjectID ) | ALL函数返回了整个Project表单,在此基础上需要找到满足Project[FinishTime] < 2/9/2015 && Project[ProjectID] = 1的所有行,来构建一个新表 | BLANK (没有满足条件的行,无法构建表单) |
MAXX (FILTER(…), Project[FinishTime]) | 没有满足条件的表单 | BLANK |
将第2行的ProjectID,Milestone以及FinishTime三个数值待入公式可以获得如下结果:
函数 | 说明 | 结果 |
---|---|---|
MilestoneDate = MAX ( Project[FinishTIme] ) | 受到ProjectID和Milestone这两个上下文影响,相当于找ProjectID=1和Milestone=Milestone B的所有数据,然后获得最大的FinishTime值 | 10/22/2015(只有当前行数据满足条件) |
ProjectID = MAX ( Project[ProjectID] ) | 同MilestoneDate | 1 |
FILTER ( ALL ( Project ), Project[FinishTime] < MilestoneDate && Project[ProjectID] = ProjectID ) | ALL函数返回了整个Project表单,在此基础上需要找到满足Project[FinishTime] < 10/22/2015 && Project[ProjectID] = 1的所有行,来构建一个新表 | 新表为:ProjectID=1,Milestone=Milestone A, FinishTime=2/9/2015(只有这一行符合条件) |
MAXX (FILTER(…), Project[FinishTime]) | 获取新表中最大的FinishTime | 2/9/2015 |
将第3行的ProjectID,Milestone以及FinishTime三个数值待入公式可以获得如下结果:
函数 | 说明 | 结果 |
---|---|---|
MilestoneDate = MAX ( Project[FinishTIme] ) | 受到ProjectID和Milestone这两个上下文影响,相当于找ProjectID=1和Milestone=Milestone C的所有数据,然后获得最大的FinishTime值 | 11/12/2015(只有当前行数据满足条件) |
ProjectID = MAX ( Project[ProjectID] ) | 同MilestoneDate | 1 |
FILTER ( ALL ( Project ), Project[FinishTime] < MilestoneDate && Project[ProjectID] = ProjectID ) | ALL函数返回了整个Project表单,在此基础上需要找到满足Project[FinishTime] < 11/12/2015 && Project[ProjectID] = 1的所有行,来构建一个新表 | 新表有两行–第1行:ProjectID=1,Milestone=Milestone A, FinishTime=2/9/2015;第2行:ProjectID=1,Milestone=Milestone B, FinishTime=10/22/2015 |
MAXX (FILTER(…), Project[FinishTime]) | 获取新表中最大的FinishTime | 10/22/2015 |
以此类推,就可以获得新的所有数据。
关于自定义函数VAR的合并拆分,请参考下一篇blog。