英文:
How is crossfilter() affecting this measure calculation in Power BI?
问题
以下是要翻译的内容:
我有两个表格:日期和销售
日期:
日期列中的值是唯一的,“2019年相关日期”的值不是唯一的。
示例数据:
日期 | 2019年相关日期 |
---|---|
2023年2月4日 | 2019年2月9日 |
2023年2月5日 | 2019年2月10日 |
2023年2月6日 | 2019年2月11日 |
2023年2月7日 | 2019年2月12日 |
2023年2月8日 | 2019年2月13日 |
2023年2月9日 | 2019年2月14日 |
2023年2月10日 | 2019年2月15日 |
销售示例数据:
日期 | 店铺 | 销售 |
---|---|---|
2019年2月11日 | A | 4 |
2019年2月14日 | A | 7 |
2019年2月11日 | B | 2 |
2019年2月14日 | B | 6 |
2019年2月11日 | C | 7 |
2019年2月14日 | C | 3 |
在日期和销售之间定义了2个关系。一个是一对多关系,连接了'Date'[Date]和Sales'[date];另一个是多对多关系,连接了'Date'[related date in 2019]和Sales'[date]
2019年WTD销售额对于2023年2月9日的计算如下:
对于2023年2月9日,WTD日期范围是2023年2月6日到2023年2月9日。基于'Date'[related date in 2019]列,这些日期对应的2019年日期是2019年2月11日到2019年2月14日。因此,2023年2月9日的WTD销售额计算为2019年2月11日到2019年2月14日的销售总额。
我有以下度量值:
2019年WTD销售额 =
VAR 本周第一天 =
SELECTEDVALUE('Date'[Date]) - WEEKDAY(SELECTEDVALUE('Date'[Date]), 2) + 1
VAR 当前日期 =
SELECTEDVALUE('Date'[Date])
RETURN
CALCULATE(
SUM(Sales[sales]),
DATESBETWEEN('Date'[Date], 本周第一天, 当前日期),
USERELATIONSHIP('Date'[related date in 2019], Sales[date])
//, CROSSFILTER('Date'[Date], Sales[date], None)
)
当未使用 CROSSFILTER('Date'[Date], Sales[date], None)
时,2023年2月9日的WTD销售额为32,这是不正确的。
当使用 CROSSFILTER('Date'[Date], Sales[date], None)
时,2023年2月9日的WTD销售额为29,这是正确的。
我的问题是:
为什么度量值中需要使用 CROSSFILTER
?在使用 USERELATIONSHIP
时,其他关系不应该被停用吗?
当不使用 CROSSFILTER
时,如何计算得到32这个值?
英文:
I have two tables: Date and Sales
Date:
Values in Date column is unique, values in “related date in 2019” is not unique.
Sample data:
Date | related date in 2019 |
---|---|
2-4-2023 | 2-9-2019 |
2-5-2023 | 2-10-2019 |
2-6-2023 | 2-11-2019 |
2-7-2023 | 2-12-2019 |
2-8-2023 | 2-13-2019 |
2-9-2023 | 2-14-2019 |
2-10-2023 | 2-15-2019 |
Sales sample data:
date | store | Sales |
---|---|---|
2/11/2019 | A | 4 |
2/14/2019 | A | 7 |
2/11/2019 | B | 2 |
2/14/2019 | B | 6 |
2/11/2019 | C | 7 |
2/14/2019 | C | 3 |
There are 2 relationships defined between Date and Sales. One is one to many between 'Date'[Date] and Sales[date]; the other is many to many between ‘Date’[related date in 2019] and Sales[date]
WTD sales 2019 for 2/9/2023 is calculated as:
For 2/9/2023, WTD dates are 2/6/2023 - 2/9/2023. The corresponding dates in 2019 for these dates based on ‘Date’[related date in 2019] are 2/11/2019 to 2/14/2019. As a result, WTD sales 2019 for 2/9/2023 is calculated as total sales for 2/11/2019 to 2/14/2019.
I have following measure:
Sales WTD 2019 =
VAR firstDayofWeek =
SELECTEDVALUE ( 'Date'[Date] ) - WEEKDAY ( SELECTEDVALUE ( 'Date'[Date] ), 2 ) + 1
VAR CurrentDate =
SELECTEDVALUE ( 'Date'[Date] )
RETURN
CALCULATE (
SUM ( Sales[sales] ),
DATESBETWEEN ( 'Date'[Date], firstDayofWeek, currentdate ),
USERELATIONSHIP ( 'Date'[related date in 2019], Sales[date] )
//, CROSSFILTER( 'Date'[Date] , Sales[date] , None )
)
When CROSSFILTER( 'Date'[Date] , Sales[date] , None )
is NOT used, WTD sales 2019 for 2/9/2023 is 32 which is incorrect.
When CROSSFILTER( 'Date'[Date] , Sales[date] , None )
is used, WTD sales 2019 for 2/9/2023 is 29 which is correct.
My questions are:
Why is CROSSFILTER
needed in the measure? Shouldn’t the other relationship be deactivated when USERELATIONSHIP
is in place?
When CROSSFILTER
is not used, how is the value of 32 calculated?
Please find pbix here:
https://drive.google.com/file/d/1Fls716yz01FgIqmQ6JVHNmDBbuy8R07k/view?usp=drive_link
Thanks.
答案1
得分: 1
Wow, 这是一个非常有趣的问题!
当不应用CROSSFILTER
时,2023-02-09
是如何计算的?
我认为计算结果可能不是您所期望的,因为尽管您使用USERELATIONSHIP
来移植活动关系,但在DAX表达式中,您还在使用主/活动关系列来建立筛选上下文。通过这样做,我认为您在维持使用活动关系。换句话说,USERELATIONSHIP
将无法移植活动关系,因为计算已经设置好了。这个行为在文档中有所提及(重点在于我的强调):
> 在USERELATIONSHIP
中,关系的状态并不重要;也就是说,关系是否处于活动状态或不活动状态并不影响函数的使用。即使关系处于非活动状态,它仍将被使用,并覆盖函数参数中未提及的任何其他活动关系可能存在的情况。
因此,对于您的2023-02-09
,您只是对2023-02-06
到2023-02-09
期间的销售金额求和,结果为32。
当应用CROSSFILTER
时,2023-02-09
是如何计算的?
当您明确关闭主要关系时,筛选上下文会变得与您期望的一样,因为您消除了使用主要关系的选项,可以说如此。
还有其他解决此问题的方法吗?
如果您不愿意在同一个表达式中同时使用CROSSFILTER
和USERELATIONSHIP
(这可以通过注释来解释,但仍然可能难以理解?),您可以选择类似以下的方法,首先使用VALUES
来计算适当的2019日期,并使用TREATAS
将筛选上下文传播到销售:
销售 WTD 2019 =
VAR _current_date =
SELECTEDVALUE ( 'Date'[Date] )
VAR _first_day_of_week =
_current_date - WEEKDAY ( _current_date, 2 ) + 1
VAR _dates =
CALCULATETABLE (
VALUES ( 'Date'[related date in 2019] ),
DATESBETWEEN ( 'Date'[Date], _first_day_of_week, _current_date )
)
VAR _out =
CALCULATE (
SUM ( Sales[sales] ),
ALL ( Sales ),
TREATAS ( _dates, Sales[sales_date] )
)
RETURN
_out
英文:
Wow, this was a really interesting question!
How is 2023-02-09
calculated when CROSSFILTER
is NOT applied?
I believe the calculation is not as you expect it to be, because while you are using USERELATIONSHIP
to transplant the active relationship, you are also using the primary/active relationship column in the DAX expression to establish the filter context. By doing this, I believe you are persisting the use of the active relationship. In other words, USERELATIONSHIP
will not be able transplant the active relationship as the calculation is set up. This behavior is alluded to in the documentation (emphasis mine):
> In USERELATIONSHIP, the status of a relationship is not important; that is, whether the relationship is active or not does not affect the usage of the function. Even if the relationship is inactive, it will be used and overrides any other active relationships that might be present in the model but not mentioned in the function arguments.
Hence, for your 2023-02-09
you are simply summing the sales amount over the period 2023-02-06
to 2023-02-09
, which turns out to be 32.
How is 2023-02-09
calculated when CROSSFILTER
is applied?
When you explicitly turn off the primary relationship, the filter context becomes what you expect, since you are removing the option of using the primary relationship altogether, so to speak.
Are there other ways to solve this?
If you are not comfortable with using both CROSSFILTER
and USERELATIONSHIP
in the same expression (this can be explained in a comment, obviously, but may still be difficult to grasp?), you can opt for something like this instead, where we first calculate the appropriate 2019 dates using VALUES
, and use TREATAS
to propagate the filter context to sales:
Sales WTD 2019 =
VAR _current_date =
SELECTEDVALUE ( 'Date'[Date] )
VAR _first_day_of_week =
_current_date - WEEKDAY ( _current_date, 2 ) + 1
VAR _dates =
CALCULATETABLE (
VALUES ( 'Date'[related date in 2019] ),
DATESBETWEEN ( 'Date'[Date], _first_day_of_week, _current_date )
)
VAR _out =
CALCULATE (
SUM ( Sales[sales] ),
ALL ( Sales ),
TREATAS ( _dates, Sales[sales_date] )
)
RETURN
_out
答案2
得分: 0
我已下载您的.pbix文件:
因此,如果没有使用CROSSFILTER
,似乎Date[Date]和Sales[date]之间的活动关系仍然保持默认的1:n关系。
在这种情况下,对于2023年2月9日,您将从那周(2/6和2/9)获得17+15 = 32。
有趣的是,如果将默认的活动关系更改为Date[2019年相关日期]和Sales[date]之间的m:n双向关系,那么在没有CROSSFILTER
的情况下,USERELATIONSHIP
也能正常工作,即应用USERELATIONSHIP
来切换到停用的1:n关系也能在没有CROSSFILTER的情况下正常工作。
编辑:
我还注意到您的度量在2023年1月1日和2022年12月31日周围存在潜在问题。[2019年相关日期]在2019年1月6日到2020年1月4日之间有一次“跳跃”。因此,在这种情况下,计算会将具有一年间隔的值相加。
或者,如果适用,您可以更轻松地在度量中计算到2019年的偏移,而不是使用第二列并避免与m:n的第二关系。
编辑2(6/6):
我刚刚做了另一件事:我添加了另一列Date[related date in 2019 distinct],其中包含不同的日期,并定义了第三个已停用的1:n关系与**Sales[date]**之间。
在这种情况下,度量也能正常工作,即在Date[Date]和Sales[date]之间保持默认的活动1:n关系,使用USERELATIONSHIP
切换到Date[related date in 2019 distinct]和Sales[date]之间的1:n关系时,无需CROSSFILTER
,可以得到预期的结果。
简要总结
- 在您的设置中,
USERELATIONSHIP
的m:n连接在没有额外的CROSSFILTER
的情况下不起作用,而活动1:n连接占上风。 - 另一方面,使用
USERELATIONSHIP
切换到另一个1:n连接与预期一样(无需CROSSFILTER
)。
解决方法
- 更改您的模型设置,将m:n连接设置为活动状态,并使用
USERELATIONSHIP
切换到1:n关系(无需CROSSFILTER
)。 - 使用公式计算日期偏移,而不是使用第二个日期列,避免m:n(个人偏好)。
- @Marcus的建议:使用虚拟表格和
TREATAS
。
英文:
I was able to download your pbix:
So, if CROSSFILTER
is not used, it seems the active relationship remains the default 1:n between Date[Date] and Sales[date]
In that case, for the 2/9/2023, you will get the 17+15 = 32 from that week (2/6 and 2/9)
Interestingly, if you change the default active relationship to the m:n with bi-directions between Date[related date in 2019] and Sales[date], the USERELATIONSHIP
works without CROSSFILTER
, i.e., applying USERELATIONSHIP to switch to the deactivated 1:n works without CROSSFILTER
Edit:
I also noticed a potential issue with your measure with the week around 1/1/2023 and 12/31/2022. There is a “jump” from 1/6/2019 to 1/4/2020 in the [related date in 2019]. So the calculation in this case sums up values with a year gap.
Alternatively, if applicable, might be easier just to calculate the offset to 2019 in your measure instead of using the second column and avoiding the second relationship with m:n
Edit 2 (6/6):
I just did one more thing: I added another column Date[related date in 2019 distinct] with distinct dates and defined a third, deactivated 1:n relation to Sales[date]
In that case the measure works just fine too, i.e., having the default, active 1:n between Date[Date] and Sales[date], using USERELATIONSHIP
to switch to the 1:n relation between Date[related date in 2019 distinct] and Sales[date] produces the expected result without the presence of CROSSFILTER
Brief Summary
- in your setup,
USERELATIONSHIP
of the m:n connection does not work without additionalCROSSFILTER
and the active 1:n connection prevails - on the other hand, using
USERELATIONSHIP
to switch to another 1:n connection works as expected (w/o the need ofCROSSFILTER
)
Workaround
- change your model setup to have the m:n connection active and to switch to the 1:n with
USERELATIONSHIP
(w/oCROSSFILTER
) instead - use a formula to calculate the date offset instead of the second date column avoiding m:n (my personal preference)
- proposal from @Marcus: use virtual table and
TREATAS
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论