Нужна формула DAX для ранжирования и устранения дубликатов - PullRequest
0 голосов
/ 09 марта 2019

У меня есть сводная таблица, которая выглядит следующим образом:

enter image description here

Проблема: доноры не складываются в общий итог, как пожертвованияделает.Это связано с тем, что возраст каждого донора определяется для каждого подарка на основе даты этого подарка, и в течение года донор может пересекать диапазоны.

Запрос: Я бы хотел, чтобы формула 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 произошел сбой, сказав, что «резюмирующие столбцы не могут иметь внешнего контекста фильтра».Согласно сноске внизу следующей страницы, это, по-видимому, всего лишь ограничение 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" )

)

1 Ответ

1 голос
/ 11 марта 2019

Я думаю, что самым простым подходом было бы создать пару рассчитанных столбцов для использования вместо них.

Давайте создадим уникальный возраст для каждого донора, выбрав его возраст для последнего пожертвования.

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.Пожалуйста, обратитесь к этой статье для получения дополнительной информации о различиях и ограничениях этих функций в различных средах.

Вы можете использовать следующее после RETURN вместо того, чтобы получить соответствующую сумму.

SUMX ( FILTER ( MaxRange, [MaxRange] IN CurrentRange ), [Amount] )

Примечание. Этот синтаксис IN, представленный выше, является более новой функцией.Используйте функцию CONTAINS для обратной совместимости.

...