暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PowerBI中的标记日期表

BISeven 2021-10-25
1876

点击上方蓝字关注我们!

   


本文翻译自SQLBI

 

我们总是将日期表标记为日期表,因为我们知道那是最佳实践。但是为什么呢?如果你没有那样做,会发生什么呢?

 

为了理解标记为日期表的重要性,我们使用一个简单的YTD计算温习一下DAX的计算上下文:

Sales YTD =
CALCULATE (
[Sales Amount],
DATESYTD ( 'Date'[Date] )
)

该度量值依赖DATESYTD函数,该函数返回了11日至当前上下文中可见的最后一个日期之间的所有日期。DATESYTD函数达到的效果与下面的表达式达到的效果一致:

VAR LastVisibleDate = MAX ( 'Date'[Date] )
RETURN
FILTER (
ALL ( 'Date'[Date] ),
'Date'[Date] >= DATE ( YEAR ( LastVisibleDate ), 1, 1 )
&& 'Date'[Date] <= LastVisibleDate
)


因此,DATESYTD函数返回的一张含有多个日期的表,更具体一点,DATESYTD函数包含了列'Date'[Date]的某些值,所以当该度量值放到report中时,才会得到我们想看到的结果:

即使这样没有让你感到惊讶,实际上应该让你感到惊讶,上面提到的度量值不能正常工作。实际上它正常工作的原因是销售表与日期表之间的关系使用了列Sales[Order Date], 该列的数据格式是日期。如果我们将Sales[Order Date]换成数字格式的话,该度量值就会失效。现在我们改变关系的关联键,用数字列[OrderDateKey] 代替 日期格式列Sales[Order Date]

 

 

下面的图表展示了新关系下的结果,该度量值YTD不再正常工作

 

让我们探究一下原因。关注4月份这一行, Sales AmountSales YTD返回1,128,104.92。下面的表达式是Sales YTD进行计算的筛选上下文:

'Date'[Calendar Year] = "CY 2007",
'Date'[Month] = "April"

因此,对Sales YTD的计算执行如下步骤:

CALCULATE (
[Sales YTD],
'Date'[Calendar Year] = "CY 2007",
'Date'[Month] = "April"
)


 

假如你展开Sales YTD,它就会变成如下:

CALCULATE (
CALCULATE (
[Sales Amount],
DATESYTD ( 'Date'[Date] )
),
'Date'[Calendar Year] = "CY 2007",
'Date'[Month] = "April"
)


 

这时,Sales Amount的计算筛选上下文是什么?我们知道DATESYTD返回的是Date[Date]中的值。因此,DATESYTD产生的筛选器只筛选Date[Date]. 它不会覆盖外部的Date[Calendar Year]

 Date[Month]上的筛选器,因此计算Sales Amount的筛选上下文变成了:

DATESYTD ( 'Date'[Date] )
'Date'[Calendar Year] = "CY 2007"
'Date'[Month] = "April"


 

结果是,筛选器20074月比DATESYTD函数返回的过滤器更具有限制性,因为过滤器取的是交集,因此结果与没有应用DATESYTD筛选器的结果相同。

 

您可以看到,顺着计算步骤,我们得到了正确的结果:公式没有正常工作,因为它是错误的。为什么同样的公式适用于关系基于Date[Date]列的呢?

 

为了简化时间智能函数的用法,当两张表基于Date类型的列建立关系时,DAX引擎会执行以下假定:当一个筛选器应用于关系的键上时-在本例中是Date[Date]-新的筛选器会覆盖该列上的其他任何筛选器。每当在Date[Date]列上应用筛选器时,它会将REMOVEFILTERS (Date)应用到筛选器上下文。只有当关系基于Date数据类型的列时,才会自动发生此

行为。

 

通过将表标记为日期表,您可以获得相同的行为——即每当在Date列上应用新筛选器时,就在表上添加REMOVEFILTERS。当将表标记为日期表时,Power BI会询问哪一列包含日历的日期。这是必需的,因为每次在特

定列上应用筛选器时,引擎都会添加REMOVEFILTERS

 

Date表标记为日期表后,结果再次正确。值得注意的是,只有当您对Date[Date]列应用筛选时,才应用REMOVEFILTERS。如果将筛选器移动到任何其他列,则不会将REMOVEFILTERS应用于筛选器上下文。

 

例如,下面的度量值在Date[Calendar Year]列上添加了一个筛选器。该引擎只替换列年上的过滤器,并保持任何其他筛选器可用:

 

Sales 2008 =
CALCULATE (
[Sales Amount],
'Date'[Calendar Year] = "CY 2008"
)

 

在上述的表中,我们假设计算CY 2007 4月份,那么度量值Sales 2008执行代码如下:

CALCULATE (
CALCULATE (
[Sales Amount],
'Date'[Calendar Year] = "CY 2008"
),
'Date'[Calendar Year] = "CY 2007",
'Date'[Month] = "April"
)


内部的筛选器2008覆盖了在列年上的筛选器,并没有覆盖月份上的筛选器,所以结果就是20084月份的结果。

 

到这里,你知道了当将一个日期表标记为日期表时发生了什么,现在可以得出结论:

1. 假如Sales表和日期表之间是基于日期列建立关系时,DAX引擎会自动的将REMOVEFILTERS应用于日期表,此时不需要将日期表标记为日期表,因为该行为会隐式发生。尽管如此,为了丰富模型元数据,以便客户端工具能够改善用户体验,继续这样做是一个好主意。


2. 如果SalesDate之间的关系基于非Date数据类型的列,则必须将该表标记为日期表,以便通过时间智能计算获得预期的行为。


3. 如果不想将表标记为日期表,可以通过向使用时间智能函数的每个度量值添加REMOVEFILTERS (date)来获得相同的行为。尽管如此,添加所有这些REMOVEFILTERS还是很无聊的,因此将表标记为日期表是一种最佳实践。


4.你可以根据需要标记更多的日期表,DAX会对所有标记为日期表的数据表执行相同的处理

 

 

Date表标记为日期表是最佳实践。如果你过去习惯这样做,你可以安全地继续这样做。现在您也知道为什么将表标记为日期表是好的。知道为什么总是比盲目遵循规则好。结果是相同的,但是这种意识对于排除错误的结果

是非常有用的。

 

 参考:

在PowerBI中,日期函数是怎样工作的?



我是BISeven,欢迎讨论,欢迎关注




 

 

 

 

 

 

 

 

文章转载自BISeven,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论