需要 DAX 公式来排名和消除重复项
Need DAX formula to rank and eliminate duplicates
我有一个枢轴 table,看起来像这样:
问题:捐助者的总和不像捐赠那样合计。这是因为捐赠者的年龄范围是根据每份礼物的日期确定的,并且在一年的时间里,捐赠者可以跨越范围。
请求:我想要一个 DAX 公式来将捐助者限制在一个范围内。在一个理想的世界中,它将基于他们在一年中的大部分时间属于哪个年龄段,但我会满足于任意保留其中一个。我相信 SQL 你可以通过分区和排名来解决这个问题。
标的样本Table:
| Donation_ID | Donor_ID | Donation_Date | Amount | age at time of gift | summary_range |
|-------------|----------|---------------|--------|---------------------|---------------|
| 1 | 100 | 3/15/2017 | 400 | 39 | <40 |
| 2 | 101 | 4/3/2017 | 50 | 69 | 60-69 |
| 3 | 100 | 5/30/2017 | 15 | 40 | 40-49 |
| 4 | 101 | 10/7/2017 | 20 | 69 | 60-69 |
| 5 | 100 | 1/23/2018 | 220 | 40 | 40-49 |
| 6 | 101 | 2/17/2018 | 25 | 70 | 70+ |
更新 - 我得到了以下代码在 DaxStudio 中工作。但后来它在 Excel 中失败了,说 "summarizecolumns cannot have outside filter context." 根据下页底部的脚注,它显然只是 Excel 的限制:https://www.sqlbi.com/articles/introducing-summarizecolumns/
EVALUATE(
// filter context of the pivot table EXCEPT no filter on age range
var fc = CALCULATETABLE(
data_table,
data_table[Donation_Date] >= date(2017,3,1),
data_table[Donation_Date] <= date(2018,2,28)
)
var hh = SUMMARIZECOLUMNS(data_table[Donor_ID], data_table[summary_range],data_table[age at time of gift], fc)
var ranked =
ADDCOLUMNS(
hh,
"RankByAge",
RANKX (
FILTER(
SUMMARIZECOLUMNS(
data_table[Donor_ID],data_table[age at time of gift],
hh
),
data_table[Donor_ID] = EARLIER(data_table[Donor_ID])
),
data_table[age at time of gift],
,
desc,
DENSE
)
)
return
// ultimately need to count the rows rather than just return them
// the second criteria would come from the filter context in Excel
FILTER(ranked, [RankByAge] = 1 && [summary_range] = "<40" )
)
我认为最简单的方法是创建几个计算列来代替使用。
让我们为每个捐赠者创建一个独特的年龄,为他们的最新捐赠选择他们的年龄。
MaxAge =
CALCULATE(
MAX(data_table[ageattimeofgift]),
ALLEXCEPT(data_table, data_table[Donor_ID])
)
然后查找与这个年龄关联的范围。
MaxRange =
LOOKUPVALUE(
data_table[summary_range],
data_table[ageattimeofgift],
data_table[MaxAge]
)
在你的枢轴 table 中使用这个而不是 summary_range
。
(注意:如果您愿意,您也可以按财政年度对 MaxAge
进行分区,以便捐赠者在单独查看年份时可以在组之间移动。)
一种更动态的方法是使用可以在过滤器上下文中读取的度量。
Distinct Donors =
VAR CurrentRange =
VALUES ( data_table[summary_range] )
VAR Summary =
SUMMARIZE (
ALLSELECTED ( data_table ),
data_table[Donor_ID],
"MaxAge", MAX ( data_table[ageattimeofgift] ),
"Amount", SUM ( data_table[Amount] )
)
VAR MaxRange =
ADDCOLUMNS (
Summary,
"MaxRange",
LOOKUPVALUE (
data_table[summary_range],
data_table[ageattimeofgift], [MaxAge]
)
)
RETURN
COUNTROWS(
FILTER(
MaxRange,
CONTAINS(
CurrentRange,
[summary_range],
[MaxRange]
)
)
)
请注意,我使用 SUMMARIZE
而不是 SUMMARIZECOLUMNS
。有关这些功能在不同环境下的差异和限制的更多信息,请参阅this article。
您可以在 RETURN
之后使用以下内容来获取相应的给定金额。
SUMX ( FILTER ( MaxRange, [MaxRange] IN CurrentRange ), [Amount] )
注意:上面的 IN
语法是较新的功能。使用 CONTAINS
函数实现向后兼容性。
我有一个枢轴 table,看起来像这样:
问题:捐助者的总和不像捐赠那样合计。这是因为捐赠者的年龄范围是根据每份礼物的日期确定的,并且在一年的时间里,捐赠者可以跨越范围。
请求:我想要一个 DAX 公式来将捐助者限制在一个范围内。在一个理想的世界中,它将基于他们在一年中的大部分时间属于哪个年龄段,但我会满足于任意保留其中一个。我相信 SQL 你可以通过分区和排名来解决这个问题。
标的样本Table:
| Donation_ID | Donor_ID | Donation_Date | Amount | age at time of gift | summary_range |
|-------------|----------|---------------|--------|---------------------|---------------|
| 1 | 100 | 3/15/2017 | 400 | 39 | <40 |
| 2 | 101 | 4/3/2017 | 50 | 69 | 60-69 |
| 3 | 100 | 5/30/2017 | 15 | 40 | 40-49 |
| 4 | 101 | 10/7/2017 | 20 | 69 | 60-69 |
| 5 | 100 | 1/23/2018 | 220 | 40 | 40-49 |
| 6 | 101 | 2/17/2018 | 25 | 70 | 70+ |
更新 - 我得到了以下代码在 DaxStudio 中工作。但后来它在 Excel 中失败了,说 "summarizecolumns cannot have outside filter context." 根据下页底部的脚注,它显然只是 Excel 的限制:https://www.sqlbi.com/articles/introducing-summarizecolumns/
EVALUATE(
// filter context of the pivot table EXCEPT no filter on age range
var fc = CALCULATETABLE(
data_table,
data_table[Donation_Date] >= date(2017,3,1),
data_table[Donation_Date] <= date(2018,2,28)
)
var hh = SUMMARIZECOLUMNS(data_table[Donor_ID], data_table[summary_range],data_table[age at time of gift], fc)
var ranked =
ADDCOLUMNS(
hh,
"RankByAge",
RANKX (
FILTER(
SUMMARIZECOLUMNS(
data_table[Donor_ID],data_table[age at time of gift],
hh
),
data_table[Donor_ID] = EARLIER(data_table[Donor_ID])
),
data_table[age at time of gift],
,
desc,
DENSE
)
)
return
// ultimately need to count the rows rather than just return them
// the second criteria would come from the filter context in Excel
FILTER(ranked, [RankByAge] = 1 && [summary_range] = "<40" )
)
我认为最简单的方法是创建几个计算列来代替使用。
让我们为每个捐赠者创建一个独特的年龄,为他们的最新捐赠选择他们的年龄。
MaxAge =
CALCULATE(
MAX(data_table[ageattimeofgift]),
ALLEXCEPT(data_table, data_table[Donor_ID])
)
然后查找与这个年龄关联的范围。
MaxRange =
LOOKUPVALUE(
data_table[summary_range],
data_table[ageattimeofgift],
data_table[MaxAge]
)
在你的枢轴 table 中使用这个而不是 summary_range
。
(注意:如果您愿意,您也可以按财政年度对 MaxAge
进行分区,以便捐赠者在单独查看年份时可以在组之间移动。)
一种更动态的方法是使用可以在过滤器上下文中读取的度量。
Distinct Donors =
VAR CurrentRange =
VALUES ( data_table[summary_range] )
VAR Summary =
SUMMARIZE (
ALLSELECTED ( data_table ),
data_table[Donor_ID],
"MaxAge", MAX ( data_table[ageattimeofgift] ),
"Amount", SUM ( data_table[Amount] )
)
VAR MaxRange =
ADDCOLUMNS (
Summary,
"MaxRange",
LOOKUPVALUE (
data_table[summary_range],
data_table[ageattimeofgift], [MaxAge]
)
)
RETURN
COUNTROWS(
FILTER(
MaxRange,
CONTAINS(
CurrentRange,
[summary_range],
[MaxRange]
)
)
)
请注意,我使用 SUMMARIZE
而不是 SUMMARIZECOLUMNS
。有关这些功能在不同环境下的差异和限制的更多信息,请参阅this article。
您可以在 RETURN
之后使用以下内容来获取相应的给定金额。
SUMX ( FILTER ( MaxRange, [MaxRange] IN CurrentRange ), [Amount] )
注意:上面的 IN
语法是较新的功能。使用 CONTAINS
函数实现向后兼容性。