在扩展表中,Allexcept()函数究竟返回什么?又为什么呢?

时间:2019-05-21 07:27:31

标签: powerbi dax

在“ DAX权威指南”中,对Allexcept函数进行了完全相同的描述:

“您还可以指定一个完整的表,而不是指定扩展表一部分的所有列”(P430)

和dax.guide上的

“ ALLEXCEPT会从Sales的扩展版本中删除过滤器,其中包括从Sales开始可以通过多对一关系访问的所有表。” https://www.sqlbi.com/articles/managing-all-functions-in-dax-all-allselected-allnoblankrow-allexcept/

它们都暗示Allexcept不用作Calculate作为过滤器参数的顶级函数时返回表,就像All()一样,而在我的实践中则有所不同:

考虑一个单表模型,例如:

Name    Datetime
John    2018/6/25
James   2018/7/7
Smith   2018/7/27
Smith   2018/11/21
Smith   2018/6/9
Mary    2019/1/31
Emily   2018/8/20
John    2018/6/9
Mary    2018/11/11
John    2018/8/21

使用带有计算列的Calendarauto()的相关日历:

YearMonth = FORMAT('Date'[Date],"yyyymm")

现在我想知道每个Name对应多少YearMonth,应该是这样的:

Name MonthNum
John    2
James   1
Smith   3
Mary    2
Emily   1

了解扩展表和Allexcept(以及上下文转换的工作原理)后,我使用了这样的公式:

Wrong = 
ADDCOLUMNS (
    VALUES ( Data[Name] ),
    "MonthNum", CALCULATE (
            DISTINCTCOUNT ( 'Date'[YearMonth] ),
            CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name] ) )
        )
    )

结果证明是:

Name    MonthNum
John    5
James   5
Smith   5
Mary    5
Emily   5

但是我确实知道如何在Calculatetable之后添加“数据”以使其正确:

  Correct = 
ADDCOLUMNS (
    VALUES ( Data[Name] ),
    "MonthNum", CALCULATE (
            DISTINCTCOUNT ( 'Date'[YearMonth] ),
            CALCULATETABLE ( Data, ALLEXCEPT ( Data, Data[Name] ) )
        )
    )

请解释“错误版本”行为不符合预期的确切原因。

2 个答案:

答案 0 :(得分:1)

有趣的问题。我不是专家,但我会尝试一下。 首先,据我了解,ALL,ALLSELECTED ...不会自行返回任何内容,它们只是清除过滤器。不确定是否相关,但可能值得一提。

为什么错误的列不起作用?与关系有很多关系。如果仅连接数据和日历表,它就会创建一个从日历到数据表的单向关系。

如果将其更改为双向关系(仅出于科学目的),即使“错误”列公式也将起作用,因为引擎可以使名称过滤器保持活动状态。

现在让我们来看看为什么正确的一个可行,而另一个在您的情况下却失败了。 让我们首先隔离计算表。

正确的-correct_calc = CALCULATETABLE ( Sheet1, ALLEXCEPT ( Sheet1, Sheet1[Name] ) )

返回

correct calculate table

一个错误时-wrong_calc = CALCULATETABLE ( ALLEXCEPT ( Sheet1, Sheet1[Name] ) )

返回

wrong calculated table

考虑到这些表,我猜想正确的表将保留“名称”过滤器,因为它们存在于计算表中,因此引擎为每个“名称”仅看到表的一部分。

另一方面,错误的名称仅保留所有日期,而与“名称”过滤器无关,因为根本不考虑“名称”值,因为VALUES ( Data[Name] )与您要在CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name] ) )上进行计算的表格。

在写答案时,我已经意识到,这并不是您要求的确切原因,因此我深表歉意。

答案 1 :(得分:0)

我做了很多测试,以找出Allexcept()的确切行为,这是我的结论:

Allexcept()具有两种不同的行为,就像All():

1。作为“ removefilter”,它从列中删除所有未从扩展表中排除的过滤器,但它本身不返回任何内容;

2。返回一个“特殊”扩展表,其中仅包含未从原始扩展表中排除的那些列。在这种情况下,结果表在可能的情况下仍会像扩展表一样工作。

行为1太清楚了,无法解释。要激活此行为,只需将allexcept()用作Calculate()或Calculatetble()的顶级函数作为过滤器参数。

行为2的证明和理解要复杂得多。

此公式证明Allexcept()可以返回表并且结果表不完整(强烈建议使用DAXStudio测试结果):

EVALUATE
GENERATE (
    VALUES ( Data[Name] ),
    CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name] ) )
)

这表明Allexcept()可以在需要时自行返回表:

EVALUATE
GENERATE ( VALUES ( Data[Name] ), ALLEXCEPT ( Data, Data[Name] ) )

这显示出Allexcept()返回的结果表是扩展的结果表:

EVALUATE
CALCULATETABLE ( 'Date', CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name],Data[Datetime],Data[Type] ) ) ) 

最后一个公式显示,当用作表返回者时,Allexcept()会忽略原始扩展表上的任何过滤器参数,这包括排除的列和未排除的列,这意味着原始扩展的所有过滤器桌子没用:

CALCULATETABLE (
    'Date',
    CALCULATETABLE (
        ALLEXCEPT ( Data, Data[Name] ),
        Data[Name] = "Tom",
        'Date'[YearMonth] ="2018-1-1"
    )
)

如果有任何建议,请发表评论!