因此,当您构建视觉对象时,会创建一个 DAX 查询以返回一个结果集,然后绘制该结果集。您可以在下面看到查询的摘录。在此之后还有更多内容,但我们拥有了解您所看到的行为所需的一切。
DEFINE
// This is a table-valued variable, which holds all dates which will be in context.
// This is based on your visual filter.
VAR __DS0FilterTable =
FILTER(
KEEPFILTERS(VALUES('Calendar'[DateKey])),
'Calendar'[DateKey] >= (DATE(2019, 1, 3) + TIME(0, 0, 1))
)
// This is a table-valued variable which holds the 1-row, 1-column table based on
// 'Calendar'[Holiday] holding the value FALSE. This is from your slicer
VAR __DS0FilterTable2 =
TREATAS({FALSE,
BLANK()}, 'Calendar'[Holiday])
// This builds up your resultset
VAR __DS0Core =
// SUMMARIZECOLUMNS lists your grouping columns, applies filters, and projects
// measures onto your resultset
SUMMARIZECOLUMNS(
// This rollup defines the grouping columns, whose values are shown on your visual.
// The rollup defines which columns get subtotals, which means we calculate an
// additional row in the resultset with filter context cleared from the column
// which is rolling up. In this case, we'll have a row with no Year context,
// but with Week context, a row with no Week context, but with Year context, and
// a row with no context on either.
ROLLUPADDISSUBTOTAL('Calendar'[Year], "IsGrandTotalRowTotal", 'Calendar'[Week], "IsDM1Total"),
// I'm separating out the filter args here. These are evaluated in a logical
// AND. The first includes all dates that pass your filter on the visual.
// The second includes only 'Calendar'[Holiday]=FALSE. The logical AND of these
// includes:
// {2019-01-04, 2019-01-05, 2020-01-02, 2020-01-03, 2020-01-04, 2020-01-05}
// Note that we're missing 2020-01-01, which passes the date test, but is a holiday.
// This is the context for evaluating our measures.
__DS0FilterTable,
__DS0FilterTable2,
// end of filter args
"Sales_Amount", 'FactSales'[Sales Amount],
"All_Sales", 'FactSales'[All Sales],
)
因此,根据评估的方式,当它到达您的度量时,日期的过滤上下文是:
<whatever is on your visual at that level>
INTERSECT
{2019-01-04, 2019-01-05, 2020-01-02, 2020-01-03, 2020-01-04, 2020-01-05}
这就是我们评估的过滤器上下文:
AllSales =
CALCULATE (
SUM ( FactSales[Sales] );
ALL ( 'Calendar'[Holiday] );
ALL ( 'Calendar'[DateKey] )
)
因此,如果没有您的 ALL ( 'Calendar'[DateKey] ),总和的过滤器上下文不包括 2020-01-01。不幸的是,'Calendar'[DateKey] > 2019-01-03 的过滤器也被此 ALL 清除,这解释了您的全部问题。总计没有 Year 上下文(基于 SUMMARIZECOLUMNS 中的汇总),没有 Week 上下文(基于相同),然后基于您的度量,没有 Holiday 上下文和 DateKey 上下文。
它适用于您的柱形图的原因是没有总计可显示。
现在,一个可能不令人满意的解决方案(因为它看起来非常相似)是定义一个新列 YearWeek 并对其进行过滤,而不是根据“日历”[DateKey] 进行过滤。
所以:
//column
'Calendar'[YearWeek] = 'Calendar'[Year] * 100 + 'Calendar'[Week]
//measure:
All Sales =
CALCULATE (
SUM ( 'FactSales'[Sales] );
ALL ( 'Calendar'[Holiday] )
)
然后您可以在 'Calendar'[YearWeek] > 201901 上定义一个过滤器。这在逻辑上是等价的,但不是 DAX 等价的。您的查询现在看起来像这样:
DEFINE
// This is now on 'Calendar'[YearWeek], instead of 'Calendar'[DateKey]
VAR __DS0FilterTable =
FILTER(
KEEPFILTERS(VALUES('Calendar'[YearWeek])),
'Calendar'[YearWeek] > 201901
)
// same as before
VAR __DS0FilterTable2 =
TREATAS({FALSE,
BLANK()}, 'Calendar'[Holiday])
// Textually same as before, but different context
VAR __DS0Core =
SUMMARIZECOLUMNS(
ROLLUPADDISSUBTOTAL('Calendar'[Year], "IsGrandTotalRowTotal", 'Calendar'[Week], "IsDM1Total"),
// Here are the filters again:
// Our intersection of 'Calendar'[Holiday]=FALSE and 'Calendar'[YearWeek]>201901.
// The 'Calendar'[YearWeek] filter is: {201902, 202001, 202002}
// so now our filter context doesn't explicitly exclude the date 2020-01-01, which
// was the problem above.
__DS0FilterTable,
__DS0FilterTable2,
// end of filters
"Sales_Amount", 'FactSales'[Sales Amount],
"All_Sales", 'FactSales'[All Sales]
)
...
根据上面的过滤器上下文,该度量工作正常。
那么,以下两种情况有什么区别:
- 过滤“日历”[Holiday] 和“日历”[DateKey]
- 过滤“日历”[假日]和“日历”[年周]
它们是同一张桌子上的两组过滤器。不同之处在于 'Calendar'[Holiday] 和 'Calendar'[DateKey] 的粒度相同。它们的交集明确排除了您想要的日期。所以你需要一个额外的ALL 来覆盖它。不过,ALL 太宽泛了,这会影响您的总数。
'Calendar'[Holiday] 和'Calendar'[YearWeek] 的粒度不同。如果您在一个 YearWeek 中有整整一周的日期都是 'Calendar'[Holiday]=TRUE,那么您会遇到与上述相同的问题,因为您在 'Calendar'[Holiday] 上的过滤器会无意中删除您要包含的整个“日历”[YearWeek]。
所有这一切的关键在于 DAX 过滤器上下文只是列中的文字值列表。重点很重要。在回答这个问题时我摸不着头脑,但将其分解为值的文字表让我回到了正轨。
这是一个非常好的问题,感谢您提出这个问题。它让我深入了解了我最近不必多想的 DAX 的一些细微差别。你的直觉是对事物应该如何表现的直觉。