阅读其他章节:
Extreme DAX-前言
Extreme DAX-第1章 商业智能中的DAX
Extreme DAX-第2章 模型设计
Extreme DAX-第3章 DAX 的用法
Extreme DAX-第4章 上下文和筛选
Extreme DAX-第5章 基于DAX的安全性
Power BI 学谦
开始本章翻译时,是5月初。当时并不知道平平无奇的5月Power BI会带来一大波更新,尤其是大杀器“字段参数”(字段参数参考文章)。
基本上可以说,本章大部分的复杂度量值书写都变的无用武之地了。一个本来需要几十行的代码,现在只需要将简单度量值拖放到参数中就可以轻松实现。
不过,本章所介绍的内容背后的原理也正是字段参数能够实现的原因。并且字段参数也不是万能的,并不能解决所有的问题。因此,本文所介绍的思想还是有较大价值的。
Power BI报表中的可视化效果是通过两种方式来使用Power BI模型中的数据。首先,列中的值用于填充可视元素,如柱形图中的轴、表视觉对象中的行标签或切片器中的选择项。我们使用术语“标签”来泛指这些元素。其次,模型中的聚合数据(通常采用DAX度量值的形式)提供视觉对象表示的结果。虽然视觉上并不清晰,但用于将视觉对象绑定到数据字段的存储桶或孔区分了这两种类型的数据使用量。例如,“轴”和“图例”需要标签数据,而“值”需要聚合数据,如图6.1所示。
图6.1 Power BI视觉对象的字段存储桶
虽然Power BI提供了许多方法来创建引人注目的报表,但有时你希望超越这些方法。本章介绍通过DAX动态更改数据绑定的两种方式的方法。绑定数据的两种方式(列和度量值)都需要自己的DAX方法实现。甚至可以将两者结合起来,以创建高度动态的视觉效果。
在本章中,我们将介绍以下主题。
- 动态度量值。
- 动态标签和坐标轴。
- 创建辅助表。
- 将动态标签与动态度量值相结合。
首先介绍一下我们将使用的Power BI模型。
6.1商业案例
自行车公司QuantoBikes使用Power BI模型来跟踪其销售情况。根据fSales表中的数据,董事会定义了三个关键绩效指标(key performance indicators,KPIs):每月销售额、年初至今销售额和12个月滚动销售额。这些 KPI 可以按订单日期、发票日期或交货日期进行分析,这些日期在fSales表中也可用。此外,董事会还对按产品、国家/地区和零售类型划分的销售额感兴趣。此信息的数据存储在三个不同的表中:Products,Customers和Cities表。
如需下载请参考异步社区本书页面配套资源的 “2.2 Dynamically changing visualizations.pbix”的模型文件。 |
---|
不同表之间的关系如图6.2所示。
图6.2 模型图
日期到fSales关系包括从日期[Date]到fSales[InvoiceDate]的一个活动关系,以及从日期[Date]到fSales[OrderDate]和从日期[Date]到fSales[DeliverDate]的两个非活动关系。所有其他关系位于两个表中具有相同名称的ID列之间。
销售数据可提供许多不同的视图,在同一报表页上为每个视图放置单独的视觉对象会导致报表单一而并非有见地。一种方法,是将视图划分到报表中的不同页面,这使得很难找到要查看的视图。
另一种方法,是使报表中的视觉对象动态化,从而允许用户只需通过选择切片器中的选项等方式选择视图。我们想要实现的是创建能够实现以下功能的DAX 度量值。
- 允许用户更改应用的计算。
- 允许用户更改销售表中使用的应用计算和日期列。
- 允许用户更改标签。
- 将上述所有内容合并到一个可视化效果中。
6.2动态度量值
通过将一个度量值添加到相应的位置(如柱形图中的“值”),视觉对象将绑定到度量值。我们想要实现的是让用户使用切片器选择 KPI,并根据该选择调整度量值。由于度量值绑定是静态的(我们无法将一个度量值动态替换为另一个度量值),因此我们需要创建一个能够对应切片器选项的 DAX 度量值。
要使此动态度量值起作用,需要执行以下几项操作。
- 我们需要为每个 KPI 创建基本度量值。
- 为了使用切片器,我们需要创建一个包含 KPI 说明的辅助表。
- 我们需要创建一个新的度量值,该度量值基于所选内容来选择相应的基本 KPI 度量值。
我们从头开始演示一遍。
6.2.1基本KPI度量值
首先,我们为 KPI 创建三个基本的 DAX 函数。
1.每月销售额将由 DAX 表函数 SUMX 计算,代码如下。
代码语言:javascript复制Sales = SUMX(fSales, fSales[UnitAmount] * fSales[SalesPrice])
如果需要有关DAX表函数的更多信息,请参见本书第4章。
2.对于年初至今销售度量,我们使用时间智能函数 TOTALYTD。
代码语言:javascript复制YTD Sales = TOTALYTD([Sales],'Date'[Date])
如果你需要有关 DAX 时间智能函数的更多信息,请参阅本书第4章。
3.最后一个基本度量值是计算12个月滚动销售额,使用 DAX 筛选器函数 CALCULATE 和时间智能函数 DATESINPERIOD 的组合。如果你需要有关 DAX 筛选器函数的更多信息,请参见第4章。在此过程中,我们将根据我们的特定需求调整此基本计算,代码如下。
代码语言:javascript复制12 mth Sales =
CALCULATE(
[Sales],
DATESINPERIOD('Date'[Date],
MAX(fSales[OrderDate]), -12, MONTH)
)
使用DATEINPERIOD时,应特别考虑参考日期(上面公式中的MAX(fSales[OrderDate]),此日期是DATESINPERIOD返回的12个月期间内的最后一个日期。从历史概况角度,参考日期是所选时间段的最后一天或MAX('Date'[Date])。例如,2020年4月的12个月滚动销售额是截至2020年4月30日的12个月的销售额。对于当前视图,这可能不是最佳选择。例如,如果今天的日期为2022年1月13日,并且计算的上下文选择2022年1月,则它将返回2021年2月1日至2022年1月31日期间的销售额。这包括近半个月没有销售,并假设我们的数据中没有未来的销售。结果是,当月滚动总额出现奇怪的下降,只有当月份前进时才会逐渐改善。当几乎每天都有订单时,则使用MAX(fSales[OrderDate])可以解决这个问题。同样,如果今天的日期是2022年1月13日,则最后一笔订单可能从2022年1月12日开始,并且运行总计是在2021年1月13日至2022年1月12日期间计算的。另一种方法是使用MIN(MAX('Date'[Date]),TODAY()),尽管在这种情况下,你需要解决所有未来月份返回当前滚动总计的问题。毕竟,选择2048年1月的上下文仍将返回今天的滚动总计。 |
---|
6.2.2创建辅助表
如果我们希望用户在报表中有一个切片器来选择其中一个KPI,则需要在模型中有一列来填充切片器。当此列不存在时,我们必须为此创建一个表,称为辅助表,或者称为控制表。我们需要的辅助表如图6.3所示。
图6.3 辅助表
辅助表包含以下三列。
- 第一列名为 Code(编号),它用于确定选择,我们始终使用2的指数来填充此列,也就是1、2、4、8等。后文会解释此序列背后的原因。
- 第二列名为 Sort(排序),它包含整数,从第一行中的1开始,每行增加1。你可以选择用此列来对 Description(说明)列进行排序(通过“按列排序”选项)。
- 第三列包含 Description(说明),这是切片器中使用的列。当然,你可以使用与所做选择更一致的名称,例如本例也可以使用 Time period(时间段)来描述。
可以使用DAX公式将辅助表创建为计算表。应为该表指定适当的名称:
代码语言:javascript复制Time period =
DATATABLE(
“Code”,INTEGER,
“Sort”,INTEGER,
“Description”,STRING,
{
{1,1,”Sales”},
{2,2,”YTD Sales”},
{4,3,”12 mths rolling”}
}
)
在创建动态DAX度量值之前,让我们讨论如何使用辅助表。辅助表与模型中的其他表没有关系。在切片器中使用“说明”列时,切片器中的选项将对列进行筛选。所以,相应的行将被选择。请注意,当切片器未显式设置单个选择时,用户可以进行多个选择。
在模型中,我们现在辅助表上有一个上下文查询,我们可以使用DAX来确定所做的选择。如果在“代码”列上使用DAX的SUM函数,则二次幂可确保所选项的每个组合对应于代码值的唯一总和。例如,总和5只能是同时选择“销售额”和“12个月滚动”的结果。因此,根据SUM('TimePeriod'[Code])的结果,我们可以决定选择哪种计算方式。
此处,还可以使用其他DAX函数,如SELECTEDVALUE,它检测列中是否只选择了一个值。但是,你仍应使用Code列,以避免在有人决定更改描述时必须更改DAX代码。我们的”二次幂”方法支持允许选择两个或多个项目的场景。 |
---|
6.2.3创建动态DAX度量值
既然我们已经知道如何检测辅助表上的切片器选项,我们可以使用 SWITCH 函数来选择正确的基本度量值。
此动态度量值的 DAX 公式如下。
代码语言:javascript复制DynHelperSales =
VAR SelectSales = SUM('Time period'[Code])
RETURN
SWITCH(SelectSales,
1, [Sales],
2, [YTD Sales],
4, [12 mth Sales]
)
我们来仔细地看一下 SWITCH 函数,此函数采用第一个参数为表达式,后面跟着任意数量的值与结果的参数对,最后也可以放一个其他选项,并以此结尾。
该函数计算表达式,并将其与值连续进行比较。当表达式和值相等时,将返回相应的结果。如果不是,则表达式将与下一个值进行比较。当所有值都不等于表达式时,该函数返回其他,如果省略其他,则返回空白值。
在我们的示例中,我们不使用其他参数。因此,如果所做的选择不会产生SWITCH列表中的值,则度量值将返回空白。
由于不选择任何内容等效于选择所有项,因此不在时间段上使用切片器将导致空白结果。对于在此Power BI模型上生成自己的报表的用户,这可能会令人困惑。因此,你可以考虑添加其他子句作为默认值,如[Sales]。
图 6.4 和图 6.5 显示了在视觉对象中使用此度量的示例输出。
图 6.4 2021年每月销售额
图6.5 2021年年初至今销售额
使用辅助表和动态DAX度量值创建动态视觉对象可大大增强用户的体验,现在用户能够对报表的一部分进行个性化设置。我们可以更进一步,将此选择与类似的方法相结合,以选择销售表中使用的日期。这样,用户可以轻松地在财务视图(发票)、销售视图(订单)和操作视图(交货)之间切换。
6.2.4动态选择计算值和日期列
在上一节中,我们开发了一个 DAX 度量值,用于按销售时段、年初至今销售额和12个月的滚动销售额之间动态切换。我们现在希望以稍微不同的方式应用类似的方法,以动态选择要使用的关系。为了让你了解我们想要实现的目标,我们添加了图6.6 和图6.7 这两个可视化效果。
图6.6 2021年每月开票金额
图6.7 2021年按月份列的已交付订单价值
我们想要做什么?在 fSales 表中,我们有三个日期列:Invoice Date 列,Order Date 列和 DeliveryDate 列,每个列都与日期表有关系。默认情况下,使用 InvoiceDate 列上的活动关系,我们希望使用切片器来动态激活其他关系之一。
这里有一个警告:我们根据 OrderDate 创建了12个月的滚动总计。由于其他日期列中的值可能不同,因此我们需要调整12个月滚动总计的DAX公式以使用正确的日期列。
同样,我们需要一个辅助表来允许我们在日期列之间进行选择。DAX公式类似于第一个辅助的公式,但第三列不同,代码如下。
代码语言:javascript复制Date selection =
DATATABLE(
“Code”,INTEGER,
“Sort”, INTEGER,
“Date selection”,STRING,
{
{1, 1, “by order date”},
{2, 2, “by invoice date”},
{4, 3, “by delivery date”}
}
)
DAX度量DynHelperSales2首先确定在两个辅助表中所做的选择,代码如下。
代码语言:javascript复制DynHelperSales2 =
VAR SelectSales = SUM('Time period'[Code])
VAR SelectDate = SUM('Date selection'[Code])
RETURN
SWITCH(SelectSales,
1, SWITCH(SelectDate,
1, CALCULATE([Sales],
USERELATIONSHIP(fSales[OrderDate], 'Date'[Date])
),
2, [Sales],
4, CALCULATE([Sales],
USERELATIONSHIP(fSales[DeliveryDate], 'Date'[Date])
)
),
2, SWITCH(SelectDate,
1, CALCULATE([YTD Sales],
USERELATIONSHIP(fSales[OrderDate], 'Date'[Date])
),
2, [YTD Sales],
4, CALCULATE([YTD Sales], USERELATIONSHIP(fSales[DeliveryDate], 'Date'[Date])
)
),
若要响应这两个辅助表选项,需要嵌套两个SWITCH函数。外部SWTICH的是上一节中使用的时间段选择器作用在SelectSales上。内部SWTICH的是激活相应的关系作用在SelectDate上。请注意,嵌套SWITCH中的选项2中尚未使用USERELATIONSHIP。由于与InvoiceDate列的关系是活动关系,因此此处不需要USERELATIONSHIP。
滚动总选项需要格外小心,因为我们需要从另一个参考日期展开。每个选项的逻辑不同,不是调用通用的[12 mth sales]度量值。每个CALCULATE函数现在都有两个筛选器参数:一个提供具有正确参考日期的滚动总周期,另一个提供正确的关系,代码如下。
代码语言:javascript复制4, SWITCH(SelectDate,
1, CALCULATE([Sales],
DATESINPERIOD(
'Date'[Date],
MAX(fSales[OrderDate]),
-12,
MONTH
),
USERELATIONSHIP(fSales[OrderDate], 'Date'[Date])
),
2, CALCULATE([Sales],
DATESINPERIOD(
'Date'[Date],
MAX(fSales[InvoiceDate]),
-12,
MONTH
),
USERELATIONSHIP(
fSales[InvoiceDate],
'Date'[Date]
)
),
4, CALCULATE([Sales],
DATESINPERIOD(
'Date'[Date],
MAX(fSales[DeliveryDate]),
-12,
MONTH
),
USERELATIONSHIP(
fSales[DeliveryDate],
'Date'[Date]
)
)
)
)
在柱形图中使用此度量值时,可以选择时间段和销售类型(由日期关系确定),从而得到如图 6.6 和图 6.7 所示的输出。
DAX公式可以避免嵌套SWITCH函数的方式重写。为此,我们使用SWITCH的方式与通常的方式略有不同,常见用法是提供一些值(通常是某些计算的结果),然后为静态值提供多个选项以将其进行比较。
但你可以反过来思考:提供静态的第一个值,并计算出要与之进行比较的值。这利用了这样一个事实,即SWITCH按参数的顺序进行所有比较,并将在第一个出现匹配时停止。
在下面的公式中,SWITCH的第一个参数是静态值TRUE()。然后,我们包括对选择组合的测试,并执行返回TRUE()的第一个测试,代码如下。
代码语言:javascript复制DynHelperSalesOption =
VAR SelectSales = SUM('Time period'[Code])
VAR SelectDate = SUM('Date selection'[Code])
RETURN
SWITCH(TRUE(),
SelectSales = 1 && SelectDate = 1,
CALCULATE([Sales],
USERELATIONSHIP(fSales[OrderDate],'Date'[Date])),
SelectSales = 1 && SelectDate = 2,
CALCULATE([Sales],
USERELATIONSHIP(fSales[InvoiceDate],'Date'[Date])),
SelectSales = 1 && SelectDate = 4,
CALCULATE([Sales],
USERELATIONSHIP(fSales[DeliveryDate],'Date'[Date])),
SelectSales = 2 && SelectDate = 1,
CALCULATE([YTD Sales],
USERELATIONSHIP(fSales[OrderDate],'Date'[Date])),
SelectSales = 2 && SelectDate = 2,
CALCULATE([YTD Sales],
USERELATIONSHIP(fSales[InvoiceDate],'Date'[Date])),
SelectSales = 2 && SelectDate = 4,
CALCULATE([YTD Sales],
USERELATIONSHIP(fSales[DeliveryDate],'Date'[Date])),
SelectSales = 4 && SelectDate = 1,
CALCULATE([Sales],
DATESINPERIOD('Date'[Date],
MAX(fSales[InvoiceDate]), -12, MONTH),
USERELATIONSHIP(fSales[OrderDate], 'Date'[Date])),
SelectSales = 4 && SelectDate = 2,
CALCULATE([Sales],
DATESINPERIOD('Date'[Date],
MAX(fSales[InvoiceDate]), -12, MONTH),
USERELATIONSHIP(fSales[InvoiceDate], 'Date'[Date])),
SelectSales = 4 && SelectDate = 4,
CALCULATE([Sales],
DATESINPERIOD('Date'[Date],
MAX(fSales[InvoiceDate]), -12, MONTH),
USERELATIONSHIP(fSales[DeliveryDate], 'Date'[Date]))
)
这样,我们就有了一个度量值,该度量值在一个公式中包含多个动态选项。当然,你可以在其他辅助表中通过更多选择来扩展它,在单个SWITCH表达式中枚举所有组合,无需嵌套更多级别的SWITCH。
在视觉对象中具有动态值是一回事,但在视觉对象中动态选择标签是另一回事,它为报表用户提供了更大的灵活性。这是以下部分的主题。
6.3动态标签
请考虑以下挑战:Power BI报表包含一个柱形图,其中包含按城市划分的销售额,报表的用户希望能够选择为此图表选择其他标签,从而允许他们按零售类型或产品组查看销售额。由于你已向他们提供了一些切片器来选择视觉对象中使用的度量值,因此你还需要使用切片器来选择图表标签。
由于本书是关于DAX的,因此我们通过DAX解决了这个问题。Power BI中还有其他选项:可以使用书签显示不同的图表,或允许报表用户使用个性化视觉对象从模型中选择其他字段。所有选项都有优点和缺点,例如易用性、需要更改DAX代码以及使用切片器或其他报表元素进行选择的可能性。我们在这里不详述其他选择。 |
---|
在本节中,将使用辅助表和自定义DAX度量值来解决此难题。
6.3.1解决方案概述
动态标签与前面讨论的动态度量值之间的根本区别在于,视觉对象中的标签无法通过计算结果填充。相反,标签使用模型中单个列的值。不过,我们要使用的标签来自模型中的三个不同表。
- 国家/地区,城市表中的一列。
- 零售类型,客户表中的一列。
- 组,产品表中的一列。
这些列中的所有值都需要位于单个列中,才能在视觉对象中使用它们。为此,我们将创建一个包含两列的辅助表。第一列包含指示标签类型(国家/地区、零售类型或组)位于行中的指示器,第二列包含三列中的值。第一列可用于选择标签类型。然后,DAX度量值将实现与三个原始表之一的动态关系。
6.3.2创建辅助表
辅助表是一个基于 DAX 公式的计算表,图6.8 显示了表格的一部分,大致对我们将要实现的目标有一个认识。
图6.8 辅助轴表
在创建此计算表的公式中,定义了三个DAX变量,每个变量创建辅助表的一部分。以下是第一个变量。
代码语言:javascript复制HelperAxes =
VAR Country =
CROSSJOIN(
ROW(“Code”, 1),
ROW(“LabelType”, “Countries”),
VALUES(Cities[Country])
)
CROSSJOIN 函数将多个表合并到一个表中,该表包含输入表中的所有列以及输入表中所有行的组合。在本例中,我们从三个输入表创建一个新表。
- ROW("Code", 1)是一个包含一行和一个包含值 1 的 Code 列的表。
- ROW("LabelType", "Countries")也是一个单行表,其值为 "Countries"。
- VALUES(Cities[Country])是一个单列表,可能有多个行,包含唯一的 Country 值。
由于两个 ROW 函数都只创建一个单行表,因此 CROSSJOIN 表中的行数是Cities[Country]列的唯一值的数量。
其他包含的标签类型也定义了类似的变量。最后,UNION 函数用于追加三个表变量的行并创建一个大的辅助表,代码如下。
代码语言:javascript复制HelperAxes =
VAR Country =
CROSSJOIN(
ROW(“Code”, 1),
ROW(“LabelType”, “Countries”),
VALUES(Cities[Country])
)
VAR Customer =
CROSSJOIN(
ROW(“Code”, 2),
ROW(“LabelType”, “RetailType”),
VALUES(Customers[RetailType])
)
VAR Product =
CROSSJOIN(
ROW(“Code”, 4),
ROW(“LabelType”, “Product Group”),
VALUES(Products[Group])
)
RETURN
UNION(Country,Customer, Product)
第二列的名称 Country 不再适用,因为它包含不同类型的信息。该名称派生自 Cities 表中的 Country 列。创建表后,双击标题名称,然后将名称 Country 更改为 AxisValues。
6.3.3使用动态标签创建度量值
现在,我们有了一个支持动态标签的辅助表,我们还需要一个DAX度量值,用于根据用户输入选择要在视觉对象中使用的标签类型。请注意,我们并没有真正改变标签;我们只需确保度量值仅返回与所选标签类型对应的标签值的结果。视觉对象不会显示没有任何值的标签。为了让你了解我们想要什么,如图6.9和图6.10所示是我们将要创建的 DynAxis 度量值的结果。
图 6.9 按国家/地区显示销售额的DynAxis度量值
图6.10 按产品组显示销售额的DynAxis度量值
与动态计算的度量一样,我们使用SWITCH来确定所做的选择,代码如下。
代码语言:javascript复制DynAxis =
SWITCH(
VALUES(HelperAxes[Code]),
1,
CALCULATE([Sales],
TREATAS(VALUES(HelperAxes[Country]), Cities[Country])
),
2,
CALCULATE([Sales],
TREATAS(VALUES(HelperAxes[Country]), Customers[RetailType])
),
4,
CALCULATE([Sales],
TREATAS(VALUES(HelperAxes[Country]), Products[Group])
)
)
请注意,code列中现在有多个具有相同值的行。为了正确确定选择,我们必须使用SELECTEDVALUE来检索所选的唯一代码值,然后确定实际值。
DAX函数TREATAS在这里执行了真正的魔术。TREATAS获取值列表,并将其作为筛选器应用于另一列,这两列不需要以任何方式相关,你可以将其解释为创建虚拟关系的TREATAS。由于DAX公式的结构方式,对于标签类型的每个选项,都会创建与另一个表(城市、客户或产品)的虚拟关系。这些表上的真实关系将筛选器传播到模型中的其他表上。
再次查看该部分开头的数字,了解视觉对象中DAX度量值的结果。切片器筛选辅助表中的LabelType列,而轴值列用于图表的y轴。
辅助表和DAX度量值已成功实现动态y轴。现在显而易见的问题是:我们是否还可以添加在动态计算部分中实现的时间段和销售类型的切片器?事实上,这并不难做到,尽管它需要一些工作。
6.4 合并动态标签和动态计算
如果要将动态标签和动态计算组合到一个视觉对象中,则需要使用我们到目前为止看到的DAX逻辑的逻辑组合。我们仍然可以使用SWITCH来确定用户所做的选择,但请记住,选项的数量增长很快。在我们的例子中,我们有三个辅助表,每个表都有三个选项,这意味着SWITCH函数中有3×3×3 = 27个选项。这意味着我们要书写大量的DAX代码!如图6.11和图6.12是结果示例。
图6.11 按国家和订单日期划分的销售额
图6.12 按零售类型和交货日期分列的12个月滚动销售额
如果要在此处把所有的代码都贴出来,恐怕太浪费纸了。我们建议你在本章的模型中找到这些代码的完整版。现在,让我们看一看一部分计算公式。如下的代码是 DAX 公式的开头,其中包含三个变量声明,用于获取用户的选择。
代码语言:javascript复制DynHelperSales3 =
VAR SelectSales = SUM('Time period'[Code])
VAR SelectDate = SUM('Date selection'[Code])
VAR SelectAxis = SUM(HelperAxes[Code])
RETURN
利用SWITCH函数再次使用我们之前看到的SWITCH(TRUE()方法。第一个选项如下所示。
代码语言:javascript复制SWITCH(TRUE(),
SelectSales = 1 && SelectDate = 1 && SelectAxis = 1,
CALCULATE(
[Sales],
USERELATIONSHIP(fSales[OrderDate],'Date'[Date]),
TREATAS(
VALUES(HelperAxes[Country]),
Cities[Country])
),
同样,所有的选项最终都需要评估为TRUE()或FALSE(),SWITCH 仅执行第一个返回TRUE的选项。此处显示的选项如下所示。
- [Sales]度量值,因为 SelectSales 等于 1。
- OrderDate 上的关系,因为 SelectDate 为 1。
- 由于SelectAxis=1,在 Cities[Country] 上使用TREATAS的虚拟关系。
作为对比,按零售类型划分的基于交货日期的12个月滚动销售额的选项使用以下DAX代码。
代码语言:javascript复制SelectSales = 4 && SelectDate = 2 && SelectAxis = 1,
CALCULATE(
[Sales],
DATESINPERIOD(
'Date'[Date],
MAX(fSales[InvoiceDate]),
-12,
MONTH
),
USERELATIONSHIP(fSales[InvoiceDate],'Date'[Date]),
TREATAS(
VALUES(HelperAxes[Country]),
Cities[Country]
)
),
尽管完整的公式很长,但所有选项都具有相似的结构。再次注意,SWITCH按顺序计算选项,直到其中一个为真;在SWITCH表达式中包含选项的顺序完全取决于你。保持合乎逻辑的顺序是一个很好的习惯,但是显而易见,通过将最常见的选项放到第一个,你可能会稍微提高一些性能。
总结
在本章中,你学习了如何使用辅助表来捕获用户输入。根据你的预期用途,辅助表可以只包含简单的几行,也可以是基于Power BI模型中其他数据的较大列表。在大多数情况下,辅助表与模型中的其他表没有关系。可以通过DAX度量值来获取以切片器中所选内容这种形式的用户输入。SWITCH函数用于根据用户输入选择适当的计算。
请记住,使用多个辅助表进行动态选择时,最好使用扩展的 SWITCH 语句,而不是使用嵌套的 SWITCH 函数。请注意,有些时候你可能并没有直接写出一个嵌套的度量值,但有可能会在 SWITCH 函数中调用另一个同样带着 SWITCH 函数的度量值。像这样堆积动态选择器往往会导致性能问题。
在下一章中,我们将深入探讨基于日历的分析。虽然我们在本章中使用了多个时间智能 DAX函数,但是许多组织使用的是 DAX 本身不支持的日历类型,因此无法直接使用这些时间智能函数。敬请期待!