从数据到信息
从信息到洞察

理解VALUES

VALUES 是 DAX 最常用的表函数之一

语法结构

VALUES ( <TableName Or ColumnName> )

VALUES 是一个表函数,可以用列名或表名作为参数,VALUES 返回参数在当前筛选上下文中的所有可见值。

  • 当使用列作为参数时,VALUES 返回列的不重复值组成的表
  • 当使用表作为参数时,VALUES 返回的表与源表具有相同的列,并且不删除重复的行
当使用表作为参数时,VALUES 只接受物理表,不接受返回表的表达式。而另一个相似的函数 DISTINCT 可以使用返回表的表达式,并且会删除表中的重复行

在存在筛选上下文的环境(例如数据透视表)中使用 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 每行返回相同的数字但有一处例外:透视表行标签上的空白等级。结果中包含的这个虚拟行用来显示未匹配产品的销售额。

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 和 ALL 都在产品表中添加空白行,以显示与销售表不匹配的值

在 Analysis Services 2012/2014 和 Power Pivot for Excel 2013 中,DISTINCT 还没有移除重复行的功能,现在你可以在 Excel 2016 和 Power BI Desktop 中使用这个函数移除重复行。

将 VALUES 函数用作标量值

虽然 VALUES 是一个表函数,你也会经常使用它来返回单值(标量值),本节你将学习 DAX 的这个特性。例如,你可以在如下表达式中找到 VALUES:如果某一筛选条件下的所有产品都有相同的颜色,则显示颜色名称:

[Color Name] :=
IF (
    COUNTROWS (
        VALUES ( Product[Color] )
    ) = 1,
    VALUES ( Product[Color] )
)

你可以在下图中看到结果。当 Color Name 列包含空白时,表示有两个或多个不同的颜色。

当 VALUES 函数返回单行时可以用作标量值

这里有趣的一点是, 即使返回表, 我们也可以将 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 模式中很常见,你会经常遇到。

案例文件下载

本文隐藏内容查看价格为3G币,请先
注:加入VIP会员可享受全站权益,性价比更高。单独购买的内容长期有效,不受时间限制。

VALUES 用法总结

VALUES 是 DAX 中使用频率很高的函数,接下来对 VALUES 在实战中的所有用法做一个梳理。

本文隐藏内容查看价格为3G币,请先
注:加入VIP会员可享受全站权益,性价比更高。单独购买的内容长期有效,不受时间限制。

 

4
说点什么

1000
 
鼓掌微笑开心憧憬爱你色并不觉得吃瓜doge二哈喵喵思考笑哭捂脸悲伤大哭抓狂汗偷笑打脸捂眼黑线问号晕拜拜闭嘴衰咒骂ok作揖
2 评论数
2 被回复的评论
2 订阅评论的人数
 
查看最近回复
查看最热评论
  订阅本文评论  
最新 最旧 得票最多
提醒
游客
Lily

VALUES 返回当前单元格中可见的唯一值列表,其中包含为不匹配值生成的空白行。

这里当前单元格是否 当前筛选上下文?

游客
Lily

老师,为什么列为参数可以删除重复行,而表确不删除重复行呢?

当使用表作为参数时,VALUES 返回的表与源表具有相同的列,并且不删除重复的行

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数