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

理解 CONTAINS

CONTAINS

CONTAINS ( <Table>, <ColumnName>, <Value>, [ <ColumnName>, <Value>, [ … ] ] )

如果指定的<table>至少存在一行满足所有<ColumnName>都有对应的<Value>,返回 true,否则 CONTAINS 返回 false。

参数 属性 描述
Table 物理表或返回表的表达式
ColumnName 可重复 使用标准 DAX 语法的现有列的名称,不支持表达式
Value 可重复 任何返回单个标量值的 DAX 表达式,该值将在 columnName 中查找

注意:

  • ColumnName 和 Value 必须成对使用,否则将报错
  • ColumnName  必须属于第一参数或第一参数的扩展表
  • 当 ColumnName 属于扩展表时,必须使用完全限定的名称(表[列名])

示例用法

使用 FILTERCALCULATETABLE 的组合可以筛选表中的行。但是,如果需要检查表中是否至少存在一行满足特定的条件,使用这些函数会产生额外不必要的计算过程。在作为第一参数的表中,CONTAINS 函数检查是否至少有一行包含后续参数中指定的所有列值。

比如你想检查销售表中是否至少包含一行单价为 99.99 的销售记录。因为 CONTAINS 的结果是一个标量值,所以可以将它嵌入到一个 ROW 函数中来执行查询:

EVALUATE
ROW ( "Sales Exist", CONTAINS ( Sales, Sales[Unit Price], 99.99 ) )

上述查询与下面这个等价:

EVALUATE
ROW (
    "Sales Exist", COUNTROWS ( CALCULATETABLE ( Sales, Sales[Unit Price] = 99.99 ) ) > 0
)

CONTAINS 为简单筛选提供了更好的性能,而 CALCULATETABLE 适用于复杂的筛选表达式。CONTAINS 只检查精确匹配,如果需要更复杂的筛选条件,则必须使用 CALCULATETABLEFILTER 或混合使用。不过,CONTAINS 函数允许你组合多列作为条件,这些列可以属于通过关系可访问的表。例如,如果澳大利亚至少包含了一行单价为 99.99 的销售记录,那么以下查询返回 TRUE:

EVALUATE
ROW (
    "Sales Australia", CONTAINS (
        Sales,
        Sales[Unit Price], 99.99,
        Customer[CountryRegion], "Australia"
    )
)

在这个示例中,上面的查询与下面这个等价:

EVALUATE
ROW (
    "Sales Australia", COUNTROWS (
        CALCULATETABLE (
            Sales,
            Sales[Unit Price] = 99.99,
            Customer[CountryRegion] = "Australia"
        )
    ) > 0
)

CONTAINS 的一个适用场景是,如果你希望从另一个表中获得至少有一个对应行的元素的列表时,可以将 CONTAINS 作为筛选条件。以下查询返回 Columbus 至少有一笔销售记录的日期列表:

EVALUATE
FILTER (
    VALUES ( 'Date'[Date] ),
    CONTAINS ( RELATEDTABLE ( Sales ), Customer[City], "Columbus" )
)
ORDER BY 'Date'[Date]

如你所见,CONTAINS 函数在每个日期所在的行上下文中计算。RELATEDTABLE 函数将此行上下文转换筛选上下文,因此 CONTAINS 仅考虑这些行的销售额,并在该日期 Columbus 至少存在一行记录时返回 TRUE。

介绍 TREATAS 时你会了解到,在所有通过查找和匹配执行虚拟筛选的函数中,TREATAS 效率最高,而 CONTAINS 适用于无法使用 TREATASINTERSECT 的场景。

15
说点什么

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

老师好,基于contains,我测试了在计算列中COUNTROWS(CALCULATETABLE(……))的应用,测试结果如图。

我理解的在这里的计算列步骤:
1. countrows忽略所在的行上下文,因此calculatetable在这里没有行上下文转换
2. 计算calculatetable的筛选器,由于没有外部筛选器,MAX(‘Product Category'[ProductCategoryKey])恒等于8
3. 在第二部基础上筛选’Product Subcategory’表
4. 计算第三步表的行数:countrows

我无法理解的是:为什么计算列的结果只有在最后一行才有值?不是应该计算列的所有行都是相同值吗?

谢谢老师指点!

Capture.PNG
成员
139****3194

老师,最后一个查询表的计值流是这样吗?
1. 将filter的第一参数表行上下文转换筛选上下文;
2. 筛选出符合以上条件的sales 表;
3. 因customer 里city 和销售表里city建立关系,将2条件relateable 到客户表;
4.contains使用,符合返回真
5,filter返回表

成员
139****3194

本文最后查询中relatable 同lastday 一样功能,也能将行上下文转换筛选上下文?请老师确认。多谢

成员
lyliuyouyang

高飞老师你好,学习了这个contains函数以后,特别是后面的contains作为筛选条件,通过relatedtable去影响一端的表的用法会更常用。不过在没学这个函数以前我通常会使用summarize+calculatetable(filter)去得到相同的结果,见table2。还有就是table1的写法总让我想起generate的用法(generate也是迭代函数,通过relatedtable去对第一参数的一端表逐行计算),我自己写了一个table3通过generate虽然没有得到和table1完全相同的结果,不过通过后续筛选和选取列最终变成一致的结果应该没什么问题,就是会觉得这两种写法很类似,虽然结果并不相同 笑哭
还有就是另外一个问题,我发现虽然related和relatedtable分别对应多端-一端和一端-多端,但是其实两者的区别很大,related更容易失效,只要不是在物理列中去获取一端的数据(比如使用了addcolumns或者selectcolumns生成的虚拟表是没办法使用related函数去获取数据的,即使是selectcolunms吧物理表中的全部的列选取出来了也不行),related就失效了,relatedtable在这个例子中总是有效,即使使用了values函数对一端的表选择列去重,还是可以通过relatedtable去获取多端表中相关的数据,感觉很神奇。其实我自己反而觉得这个地方把relatedtable当作成calculatetable更好理解一些,calculatetable会把values生成的表的行上下文转换为筛选上下文,从而得到相关的数据。当然可能是我对于related和relatedtable理解不够透彻才会产生这种疑惑吧,望老师解惑。

批注 2020-05-03 100309.jpg
DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数