CONTAINS
CONTAINS ( <Table>, <ColumnName>, <Value>, [ <ColumnName>, <Value>, [ … ] ] )
如果指定的<table>至少存在一行满足所有<ColumnName>都有对应的<Value>,返回 true,否则 CONTAINS 返回 false。
参数 | 属性 | 描述 |
---|---|---|
Table | 物理表或返回表的表达式 | |
ColumnName | 可重复 | 使用标准 DAX 语法的现有列的名称,不支持表达式 |
Value | 可重复 | 任何返回单个标量值的 DAX 表达式,该值将在 columnName 中查找 |
注意:
- ColumnName 和 Value 必须成对使用,否则将报错
- ColumnName 必须属于第一参数或第一参数的扩展表
- 当 ColumnName 属于扩展表时,必须使用完全限定的名称(表[列名])
示例用法
使用 FILTER 和 CALCULATETABLE 的组合可以筛选表中的行。但是,如果需要检查表中是否至少存在一行满足特定的条件,使用这些函数会产生额外不必要的计算过程。在作为第一参数的表中,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 只检查精确匹配,如果需要更复杂的筛选条件,则必须使用 CALCULATETABLE、FILTER 或混合使用。不过,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。
老师好,基于contains,我测试了在计算列中COUNTROWS(CALCULATETABLE(……))的应用,测试结果如图。
我理解的在这里的计算列步骤:
1. countrows忽略所在的行上下文,因此calculatetable在这里没有行上下文转换
2. 计算calculatetable的筛选器,由于没有外部筛选器,MAX(‘Product Category'[ProductCategoryKey])恒等于8
3. 在第二部基础上筛选’Product Subcategory’表
4. 计算第三步表的行数:countrows
我无法理解的是:为什么计算列的结果只有在最后一行才有值?不是应该计算列的所有行都是相同值吗?
谢谢老师指点!
老师,最后一个查询表的计值流是这样吗?
1. 将filter的第一参数表行上下文转换筛选上下文;
2. 筛选出符合以上条件的sales 表;
3. 因customer 里city 和销售表里city建立关系,将2条件relateable 到客户表;
4.contains使用,符合返回真
5,filter返回表
本文最后查询中relatable 同lastday 一样功能,也能将行上下文转换筛选上下文?请老师确认。多谢
高飞老师你好,学习了这个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理解不够透彻才会产生这种疑惑吧,望老师解惑。