10.1 IF 和 SWITCH
基础
IF 是最常见的逻辑函数,用于条件判断,它的语法和Excel相同。SWITCH是多层IF的简化形式,本质是IF嵌套,但是写法更优雅,以下是两个示例:———— IF形式 ——————SizeDesc =IF(DProduct[Size]=”S”,”Small”,IF(Product[Size]=”M”,”Medium”,IF(Product[Size]=”L”,”Large”,IF(Product[Size]=”XL”,”Extra Large”,”Other”))))———— SWITCH等价形式 —————SizeDesc =SWITCH(Product[Size],”S”,”Small”,”M”,”Medium”,”L”,”Large”,”XL”,”Extra Large”,”Other”)除了用第一参数返回的值作为判断条件,SWITCH还有一种实用的写法,适合用在逻辑判断中,在逻辑函数一文中介绍过,SWITCH(TRUE(),Product[Size]=”XL”&& Product[Color]=”Red”,”Red and XL”,Product[Size]=”XL”&& Product[Color]=”Blue”,”Blue and XL”,Product[Size]=”L”&& Product[Color]=”Green”,”Green and L”)使用TRUE作为第一参数表示:“返回条件求值为TRUE的第一个结果”。## 注意 IF函数看似结构简单,但隐藏了一些容易被忽视的细节。### 变体类型 变体数据类型用于可能返回不同数据类型的度量值,主要与IF配合使用,变体类型取决于度量值使用的条件表达式。例如,下面的语句可以返回整数或字符串,所以它返回一个变体类型:IF([measure]>0,1,”N/A”)变体只适用于度量值,不能用于计算列,因为计算列必须具有统一的数据类型计算列的必须使用统一的数据类型### 标量函数 IF和SWITCH都是标量函数,所以它们只能输出标量值,不能输出表,你不能在IF的条件中直接返回表表达式,所以下面的写法是错误的:VAR Granularity =IF(SELECTEDVALUE(‘Dynamic Axis’[Granularity])=”Monthly”,DATESMTD(‘Calendar’[date]),DATESYTD(‘Calendar’[date]))RETURNCALCULATE(SUM([SomeField]),Granularity)### 逻辑表达式的一种特殊情况 当IF的返回条件中出现一个逻辑表达式,即“true”或“false”时,整个公式返回逻辑表达式或文本,忽略数字和空值。IF(1=1,BLANK(), TRUE)返回FALSEIF(1=1,100, FALSE)返回TRUE## 使用变量优化IF和SWITCH 在DAX表达式中使用变量替换相同度量值的多次引用可以提高公式可读性、优化公式的效率,因为正确地使用变量可以防止对同一表达式多次计算。然而,在某些情况下,变量的使用也可能适得其反,对性能产生负面影响。首先,让我们演示变量如何优化公式的执行。考虑下面的报告,Sales YTDOY 计算的是今年的累计销售额与去年累计销售额的差值,仅考虑两年中都有销售额的月份Sales YTDOY :=CALCULATE(SUMX(VALUES(‘Date’[Calendar Year Month Number]),VAR CurrentSales =[Sales Amount]VAR PreviousSales =[Sales LY]RETURNIF(AND(CurrentSales <>0,PreviousSales <>0),CurrentSales - PreviousSales)),DATESYTD(‘Date’[Date]))Sales YTDOY 公式对于SUMX第一参数中的月份,每月只计算一次[Sales Amount]和[Sales LY],在后续的IF条件中重复调用。对比下面的公式,你会发现这种写法的效率高的多。Sales YTDOY slow :=CALCULATE(SUMX(VALUES(‘Date’[Calendar Year Month Number]),IF(AND([Sales Amount]<>0,[Sales LY]<>0),[Sales Amount]-[Sales LY])),DATESYTD(‘Date’[Date]))尽管DAX引擎可能会在相同的筛选上下文([Sales Amount]和[Sales LY])中复用相同度量获得的结果,但这种理想情况并非始终发生。在这种情况下,变量是确保更好的优化代码执行的好方法。这种理想情况称为短路计算,随着DAX引擎的更新,对于一些并不复杂的IF判断,引擎可以自动执行短路计算,以提高效率。但是对于复杂的表达式,你不能依赖引擎的判断,使用变量是最佳方法。需要注意的是,变量的计算受定义环境的影响。例如,如果变量定义在条件判断之前,则无论条件是否命中,都将计算该变量。当报告中存在独立的切片器时,这将对性能产生很大影响。要理解一点,参考下面这个报告,右侧时段选择表定义了切片器,该切片器控制矩阵的可见列,矩阵使用Sales度量值。sales度量值有两种定义方式,请对比两者的不同低效写法高效写法Sales vSlow =VAR PeriodSelection =SELECTEDVALUE(‘Time Selection’[PeriodSelector])VAR SalesAmount =[Sales Amount]VAR SalesLY =[Sales LY]VAR SalesYOY =[Sales YOY]VAR SalesYTD =[Sales YTD]VAR SalesLYTD =[Sales LYTD]VAR SalesYTDOY =[Sales YTDOY]RETURNSWITCH(PeriodSelection,”C”, SalesAmount,”LY”, SalesLY,”YOY”, SalesYOY,”YTD”, SalesYTD,”LYTD”, SalesLYTD,”YTDOY”, SalesYTDOY,BLANK())考虑到每个变量只使用一次,vSlow其实是一种冗余写法。不过,在实际使用中我们会使用这种形式一拖N的度量值来避免在模型中定义大量单独的度量值,使用vFast写法,可以减少公式代码量,并且获得更好的性能。### 短路计算 在这种多条件计算中,我们希望公式在命中指定的分支时才计算对应的变量。在IF和SWITCH函数的计值过程中,这种优化策略称为短路计算,它是通过将特定筛选器应用于IF和SWITCH求值分支的筛选上下文来实现的。由于Sales vSlow度量值中的变量是在IF和SWITCH之前定义的,因此筛选上下文的更改不适用于变量的计算。所有变量(和所有度量值)的计算将不考虑示例报表的区间切片器中所做的选择。### 变量使用规范 在特定场景中,此特性可能对DAX度量值的性能产生严重影响,因此,使用变量最好遵循以下规则:
- 当在同一筛选上下文中多次计算同一DAX表达式时,请将其定义为变量并在后续计算时引用该变量,而不是引用DAX表达式。
- 当在IF或SWITCH的分支中计算DAX表达式时,只要有必要,请在条件分支中将表达式定义为变量-这将保持短路优化。
- 如果仅在条件分支中使用变量,请不要在IF和SWITCH语句之外分配变量。
- IF和SWITCH的第一个参数可以使用在IF和SWITCH之前定义的变量,这不会影响性能。
关于第三条中,你可以用下面的公式理解IF(
,— 条件分支1VAR variablename = RETURN ,— 条件分支2VAR variablename2 = RETURN ,) 参考阅读:印象笔记邮件分享标签:条件判断函数上一篇ALLSELECTED### 相关推荐