【问题标题】:Need DAX formula to rank and eliminate duplicates需要 DAX 公式来排名和消除重复项
【发布时间】:2019-03-08 22:14:14
【问题描述】:

我有一个如下所示的数据透视表:

问题:捐助者不会像捐赠那样加起来总和。这是因为捐赠者的年龄范围是根据每份礼物的日期确定的,并且在一年的过程中,捐赠者可以跨越范围。

请求:我想要一个 DAX 公式来将捐赠者限制在一个范围内。在一个理想的世界里,这将基于他们一年中大部分时间属于哪个年龄段,但我会满足于任意保留其中一个。我相信在 SQL 中,您可以通过分区和排名来解决这个问题。

基础表样本:

| 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 不能有外部过滤器上下文”。根据下一页底部的脚注,这显然只是 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" )

)

【问题讨论】:

  • 如果您提供更具描述性的标题并包含数据表外观示例,您更有可能获得帮助。 mcve 是理想的选择。
  • 谢谢@AlexisOlson。我对否决票感到沮丧,但这也许可以解释这一点。我已编辑问题以提供不同的标题和示例数据。
  • 在新社区中制定规范总是很困难。您的修改使这个问题变得更好!

标签: dax powerpivot


【解决方案1】:

我认为最简单的方法是创建几个计算列来代替。

让我们通过选择他们最近一次捐赠的年龄来为每个捐赠者创建一个独特的年龄。

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]
    )

在您的数据透视表中使用它而不是 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 函数实现向后兼容性。

【讨论】:

  • 哇,谢谢亚历克西斯!您的第二种动态方法绝对是我想要完成的。我有一个小问题:它不喜欢 IN 语法。运行检查公式失败,代码原样。我可以通过使用 `[MaxRange] = TOPN(1,CurrentRange)` 来使其适用于上图所示的数据透视表。但是,如果您重新排列枢轴并取消范围,这显然会失败。有什么想法吗?
  • 啊,IN 语法是 Excel 还没有的较新的 DAX 功能。您可以改用CONTAINS 函数。这是一篇有用的相关文章:sqlbi.com/articles/the-in-operator-in-dax
猜你喜欢
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多