[知识体系] 理解 LOOKUPVALUE

  [复制链接]
查看253374 | 回复182 | 2021-2-21 18:56:57 | 显示全部楼层 |阅读模式
LOOKUPVALUE 是一个搜索函数,它在作为参数的列中搜索与提供的值相等的列值,并最终从表中检索一个可用值,整个过程忽略任何筛选上下文

LOOKUPVALUE
  1. LOOKUPVALUE( <result_columnName>, <search_columnName>, <search_value>, [<search_columnName>, <search_value>]…[ <alternateResult>] )
复制代码
参数属性描述
Result_ColumnName要返回的值所在的列名。列必须使用标准 DAX 语法命名,通常是完全限定的,不支持表达式。
Search_ColumnName可重复在与 Result_columnName 相同的表中或扩展表中,执行查找的现有列的名称,列必须使用标准 DAX 语法命名,通常是完全限定的。不支持表达式。
Search_Value可重复标量表达式(不引用正在搜索的同一表中的任何列)
Alternate_Result可选当第一参数结果为空或多个不重复值时的替代结果,如果省略此参数,为空时返回 BLANK,多值返回错误


函数返回匹配所有 search_column 和 search_value 组合的行上的 result_column 的值。


如果没有满足所有搜索值的匹配行,返回一个空白或 alternateResult(如果提供)。换句话说,如果只有部分条件匹配,函数将不会返回查找值。

报错情形

如果有多个行匹配搜索值,并且它们的 result_column 值都相同,则返回该值。但是,如果 result_column 返回不同的值,则函数返回错误或 alternateResult(如果提供)。也就是说,匹配到的结果可以在列中重复显示,但值必须唯一。
  1. 最高价时间:=LOOKUPVALUE(‘测试 2′[日期],’测试 2′[最高],’测试 2′[最高价])
复制代码

7101211936391.png

最高价对应多个不同日期的时候,LOOKUPVALUE 返回错误

等价表达式



LOOKUPVALUE 在引擎内部计算时使用以下语法:
  1. VAR SearchValue = <Search_Value>
  2. RETURN
  3.     CALCULATE (
  4.         SELECTEDVALUE ( <Result_ColumnName>, <Alternate_Result> ),
  5.         FILTER (
  6.             ALLNOBLANKROW ( <Search_ColumnName> ),    //忽略外部上下文
  7.             <Search_ColumnName> == SearchValue        //严格相等,BLANK 不等同于 0 或空字符串
  8.         ),
  9.         ALL ( <table_of_Result_ColumnName> )          //忽略结果列所在表提供的所有筛选器
  10.     )
复制代码

从等价表达式的 6,7,9 行可以分别读出有价值的信息,如公式中的标注所示,通过第 6 和第 9 行你可以明白为什么 LOOKUPVALUE 忽略外部筛选器,其中第 9 行的写法在某些特殊情况下可以导致异常,本文最后将提供一个案例。

示例用法

以下查询将 CAD 货币代码转换为相应的货币名称:
  1. EVALUATE
  2. ROW (
  3.     "Currency", LOOKUPVALUE (
  4.         Currency[Currency],
  5.         Currency[Currency Code], "CAD"
  6.     )
  7. )
复制代码


7101211936392.jpeg

LOOKUPVALUE 函数忽略现有的筛选上下文,直接在目标表中执行查找。当表达式在发生上下文转换的迭代环境中执行时,这种行为特别有用。

你可以指定更多的列来执行匹配操作,还可以通过关系引用相关表的列。以下查询返回满足 Contoso 品牌、Deluxe 类别、颜色为银色的音频类别的产品:
  1. EVALUATE
  2. ROW (
  3.     "Product", LOOKUPVALUE (
  4.         Product[Product Name],
  5.         Product[Color], "Silver",
  6.         Product[Brand], "Contoso",
  7.         Product[Class], "Deluxe",
  8.         'Product Category'[Category], "Audio"
  9.     )
  10. )
复制代码


7101211936393.jpeg



如果有存在多行与搜索值匹配,结果将视情况而定:


  • 如果<result_column_name>返回不同的值,函数将返回错误.
  • 如果<result_column_name>返回唯一值,即使表中的多个行与搜索值匹配,LOOKUPVALUE 函数也只返回该唯一值。
  • 如果没有匹配的行,函数返回空白值。


例如,以下查询返回月份编号为 3 对应的月份名称,即使返回的值可能有几百行,但它们有相同的唯一值:
  1. EVALUATE
  2. ROW (
  3.     "Month Name", LOOKUPVALUE (
  4.         'Date'[Month],
  5.         'Date'[Month Number], 3
  6.     )
  7. )
复制代码


7101211936394.jpeg

大多数情况下,当你有行上下文并且需要通过关系获取相关表某一列的值时,可以使用 RELATED 函数执行查找操作,它的性能更好。但是,如果两个表在数据模型中没有可用关系,或者需要实现基于特定逻辑的查找时,可以使用 LOOKUPVALUE 或 TREATAS 代替 RELATED

某些情况下,你也可以使用 CALCULATE 函数重写 LOOKUPVALUE,但这并不是最佳实践。例如,可以按以下方式重写上面的查询:
  1. EVALUATE
  2. ROW (
  3.     "Month Name", CALCULATE (
  4.         VALUES ( 'Date'[Month] ),
  5.         'Date'[Month Number] = 3
  6.     )
  7. )
复制代码
循环依赖的 Bug

LOOKUPVALUE 在大部分情况下可以正常工作,但某些特殊情况可能导致错误提示,一旦你理解 LOOKUPVALUE 内部使用的表达式,就可以解决这类问题。在这里举一个简单的例子。


两张表的数据和关系如下图所示,两表通过 C1 建立双向关系,我们在 Table2 新建计算列使用 LOOKUPVALUE 在 Table1 中查找对应的 C2 的值:


7101211936395.png

案例数据示意图


从示意图可以看出,Table2 的计算列 Cal Column1 得到了正确的结果,问题出现在 Cal Column2,这个计算列使用了简单的等式
  1. Cal Column2 = 'Table2'[Cal Column1]
复制代码

却得到了循环依赖的错误提示。这是为什么?当你理解了等价表达式,就能回答这个问题。

让我们再重新研究一下 LOOKUPVALUE 的等价表达式:
  1. VAR SearchValue = <Search_Value>
  2. RETURN
  3.     CALCULATE (
  4.         SELECTEDVALUE ( <Result_ColumnName>, <Alternate_Result> ),
  5.         FILTER (
  6.             ALLNOBLANKROW ( <Search_ColumnName> ),
  7.             <Search_ColumnName> == SearchValue      
  8.         ),
  9.         ALL ( <table_of_Result_ColumnName> )      
  10.     )
复制代码

这次让我们把注意力放在表达式的第 9 行,这里的 ALL 忽略了结果列所在的整张表(Table1),在绝大部分情况下,它可以有效的忽略来自外部的筛选器。但是本例中两表的关系是双向筛选,这就意味着对 Table2 的筛选可以传递到 Table1,只忽略 Table1 的筛选条件将不起作用。此时新建的 Cal Column2 将在 Cal Column1 的等价表达式中通过 CALCULATE 执行上下文转换筛选 Table1,最终影响 Cal Column1 的结果,这意味着 Cal Column1 依赖于 Cal Column2。又因为 Cal Column2 = &#8216;Table2&#8242;[Cal Column1],所以 Cal Column2 又依赖于 Cal Column1,循环依赖就发生了。
7101211936396.png



导致此问题的关键是双向筛选,而单向筛选不会遇到此问题。如果你需要维持筛选关系为双向,可以按如下方式改写表达式,忽略来自 Table2 的筛选,此时新建列将不再筛选 Table1:
  1. Cal Column1 New =
  2. CALCULATE (
  3.     DISTINCT ( Table1[C2] ),
  4.     FILTER ( ALLNOBLANKROW ( Table1[C1] ), Table1[C1] = Table2[C1] ),
  5.     ALL ( Table2 )
  6. )
复制代码
回复

使用道具 举报

mende | 2021-4-24 15:16:07 | 显示全部楼层
支持,赞一个
回复

使用道具 举报

→有几坏← | 2021-5-20 20:10:14 | 显示全部楼层
说的不错,学习了
回复

使用道具 举报

kinki_L | 2021-6-16 19:28:21 | 显示全部楼层
我是个凑数的。。。
回复

使用道具 举报

蓝精灵 | 2021-6-24 13:18:30 来自手机 | 显示全部楼层
发发呆,回回帖,工作结束~
回复

使用道具 举报

hylinfeng | 2021-7-8 08:01:56 | 显示全部楼层
学习下
回复

使用道具 举报

着迷 | 2021-8-22 23:57:03 来自手机 | 显示全部楼层
纯粹路过,没任何兴趣,仅仅是看在老用户份上回复一下
回复

使用道具 举报

银欧SRV | 2021-9-3 08:05:50 来自手机 | 显示全部楼层
支持,一直很喜欢老师的课程
回复

使用道具 举报

火嘴 | 2021-10-4 08:35:59 来自手机 | 显示全部楼层
垃圾内容,路过为证。
回复

使用道具 举报

tanyq8290 | 2021-10-6 11:16:38 来自手机 | 显示全部楼层
前排,哇咔咔
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则