VALUES 是 DAX 最常用的表函数之一
语法结构
VALUES ( <TableName Or ColumnName> )
VALUES 是一个表函数,可以用列名或表名作为参数,VALUES 返回参数在当前筛选上下文中的所有可见值。
- 当使用列作为参数时,VALUES 返回列的不重复值组成的表
- 当使用表作为参数时,VALUES 返回的表与源表具有相同的列,并且不删除重复的行
在存在筛选上下文的环境(例如数据透视表)中使用 VALUES 函数时,VALUES 返回的唯一值将受到筛选器的影响,如果你要忽略筛选器的影响,可以使用 ALL。例如,下面这个度量值对 CustomerKey 列在当前筛选上下文中可见的非重复值的数量进行计数
[NumOfCustomers] := COUNTROWS ( VALUES ( Sales[CustomerKey] ))
理解 VALUES 和 DISTINCT
ALL 函数使用一列作为参数时可以返回唯一值列表,DAX 还提供了另外两个类似的函数用来返回一列的唯一值:VALUES 和 DISTINCT。
VALUES 和 DISTINCT 在没有任何其他筛选器的 EVALUATE 语句中,与 ALL 函数的作用看起来相同,但是, 当你将这些函数放在 DAX 度量值中时,可以观察到不同的行为,因为计算发生在数据透视表每个单元格不同的上下文中。请考虑以下度量值:计算品牌列和产品表的唯一值的数量。
[Products]:= COUNTROWS ( Product ) [Values Brands]:= COUNTROWS ( VALUES ( Product[Brand] ) ) [Distinct Brands]:= COUNTROWS ( DISTINCT ( Product[Brand] ) ) [Values Sizes]:= COUNTROWS ( VALUES ( Product[Size] ) ) [Distinct Sizes]:= COUNTROWS ( DISTINCT ( Product[Size] ) )
VALUES 返回当前单元格中可见的唯一值列表,其中包含为不匹配值生成的空白行。DISTINCT 也是相同的行为,但不返回空白行。但是,如果空值作为列的有效值出现,那么这两个函数都将包含空白行。所以它们的唯一的区别是是否添加空行以处理由参照完整性产生的关系中的缺失值。
下面的例子可能有助于澄清这种差异,如下图所示,每个产品类别都筛选出不同数量的产品。例如, 有 360 种产品是豪华等级, 其中包含 11 种唯一品牌和 204 种唯一尺寸。VALUES 和 DISTINCT 每行返回相同的数字但有一处例外:透视表行标签上的空白等级。结果中包含的这个虚拟行用来显示未匹配产品的销售额。
从总计中可以看到另一个差异。应用于 Product[Brand] 列的 VALUES 函数返回的值不同于同一列的 DISTINCT。但是,这种情况不会发生在 Products[Size] 列上,VALUES 和 DISTINCT 返回相同的值。原因是,尺寸的唯一值里已经包含了空值(至少有一个产品的尺寸是空白的), 因此添加空白产品不会向尺寸列添加新的唯一值。
当没有筛选器时,DISTINCT 的行为对应于 ALLNOBLANKROW,而 VALUES 的行为则对应于 ALL。
VALUES 也接受表作为参数,在这种情况下,它返回当前单元格中可见的整个表,包括由于参照完整性产生的空行。例如,在数据模型中考虑以下度量值,其中销售表与产品表存在关系,并且包含与任何现有产品都不匹配的产品交易记录。
[Products]:= COUNTROWS ( Product ) [Values Products]:= COUNTROWS ( VALUES ( Product ) ) [All NoBlank Products]:= COUNTROWS ( ALLNOBLANKROW ( Product) ) [All Products]:= COUNTROWS ( ALL ( Product ) )
在下图所示的这个案例中,你可以看到当没有筛选器时,VALUES 函数和 ALL 函数的不同行为,包括添加的空白行以显示未匹配产品的销售额。[Products]这个度量值在这里统计产品表的行数,忽略可能的空行,与 ALLNOBLANKROW 在总计行的行为相同。
将 VALUES 函数用作标量值
虽然 VALUES 是一个表函数,你也会经常使用它来返回单值(标量值),本节你将学习 DAX 的这个特性。例如,你可以在如下表达式中找到 VALUES:如果某一筛选条件下的所有产品都有相同的颜色,则显示颜色名称:
[Color Name] := IF ( COUNTROWS ( VALUES ( Product[Color] ) ) = 1, VALUES ( Product[Color] ) )
你可以在下图中看到结果。当 Color Name 列包含空白时,表示有两个或多个不同的颜色。
这里有趣的一点是, 即使返回表, 我们也可以将 VALUES 的结果用作标量值。这不是 VALUES 的特殊行为, 它是 DAX 语言的一种更一般的行为:
如果返回表的表达式结果是包含一行一列的表, 则可以转换为标量值, 这种转换在需要时自动完成。
实际上, 如果结果恰好是一行和一列, 则可以将任何返回表的表达式用作标量值。如果表返回多行, 在执行时会出现此错误: “该表达式引用多列,多列不能转换为标量值”。因此,在表表达式返回多行(在编写 DAX 表达式时,你应该已经知道表表达式是否只返回一行)的情况下,你应该始终使用返回不同结果的条件来保护对标量值的转换。
上一个示例的 Color Name 度量值使用 COUNTROWS 检查产品表的颜色列是否只有一个选中的值。实现相同控制的一种更简单的方法是使用 HASONEVALUE,它执行相同的检查,如果列只有一个值时返回 TRUE,否则返回 FALSE。以下两种语法是等价的:
COUNTROWS ( VALUES ( <column> ) ) = 1 ----------- 等价用法 ---------------- HASONEVALUE ( <column> )
你应该使用 HASONEVALUE 而不是 COUNTROWS,原因是它更易于阅读,而且计算的时候可能会稍微快一些。下面是基于 HASONEVALUE 的 Color Name 度量值的推荐写法:
[Color Name] := IF ( HASONEVALUE ( Product[Color] ), VALUES ( Product[Color] ) )
通常使用 VALUES 作为标量表达式的原因是,它返回单个列,并可能返回单个行,这取决于计值上下文。使用 VALUES 作为标量表达式在许多 DAX 模式中很常见,你会经常遇到。
案例文件下载
VALUES 用法总结
VALUES 是 DAX 中使用频率很高的函数,接下来对 VALUES 在实战中的所有用法做一个梳理。
这个有个错别字
ALL是不考虑参照完整性吧?
老师我有个问题,在第五章中(使用calculate函数计算百分比)这里的all+values,我用distinct发现结果一样,为什么都是用values而不用distinct呀
老师,第二版啥时候出版啊?
老师,查看不了隐藏内容,帮着看看是否已过期?该续费了
VALUES 返回当前单元格中可见的唯一值列表,其中包含为不匹配值生成的空白行。
这里当前单元格是否 当前筛选上下文?
老师,为什么列为参数可以删除重复行,而表确不删除重复行呢?
当使用表作为参数时,VALUES 返回的表与源表具有相同的列,并且不删除重复的行