Проблема с запросом DAX: расчет текущего значения с использованием расчетного значения предыдущей строки

У меня есть набор данных, представляющий изменения состояния батареи, и мне нужно вычислить ResidualCapacity для каждого изменения состояния. ResidualCapacity следует рассчитывать как предыдущий ResidualCapacity плюс текущий ChargeVariation, не превышая UpperBound, равного 80.

Вот структура моей таблицы с правильным **ResidualCapacity**значением:

Чейнджстате Изменение заряда Остаточная емкость 1 70 70 2 -5 65 3 20 80 4 -10 70 5 -5 65
  • ChangeState: Индекс, показывающий хронологический порядок изменения состояния батареи.
  • ChargeVariation: Сумма, на которую изменилась начисление.
    • ChargeVariation < 0: Использование батареи
    • ChargeVariation > 0: Зарядка аккумулятора
  • ResidualCapacity: Расчетный столбец, который должен показывать остаточную емкость батареи после каждого изменения состояния.

Моя цель состоит в том, чтобы ResidualCapacity всегда было предыдущим ResidualCapacity плюс текущим ChargeVariation, но оно никогда не должно превышать UpperBound из 80.

Я написал следующий запрос DAX, но он возвращает неверный результат для последнего значения ResidualCapacity (он возвращает 70 вместо 65):

ResidualCapacity = 
    VAR UpperBound = 80
    VAR CurrentVariation = 'Table'[ChargeVariation]
    VAR CurrentState = 'Table'[ChangeState]

    VAR PervVariationRT = 
        SUMX(
            FILTER(
                'Table',
                'Table'[ChangeState] < CurrentState
            ),
            'Table'[ChargeVariation]
        )

    VAR Result =
        MIN(CurrentVariation + MIN(PervVariationRT, UpperBound), UpperBound)

    RETURN
        Result

Как изменить этот запрос, чтобы правильно рассчитать вычисляемый столбец ResidualCapacity для каждого изменения состояния?

Согласитесь ли вы на решение запроса мощности?

davidebacci 07.08.2024 14:04

@davidebacci Да, решение для запроса мощности тоже подходит

pofferbacco 07.08.2024 14:12

Не забудьте отметить решение как решенное и проголосовать, если решение помогло. Спасибо

davidebacci 07.08.2024 18:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
74
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Не могли бы вы просто изменить выражение «Результат», чтобы проверить, равно ли текущее состояние изменения максимальному состоянию изменения таблицы, и добавить соответствующий вариант оплаты, если да?

ResidualCapacity = 
    VAR UpperBound = 80
    VAR CurrentVariation = 'Table'[ChargeVariation]
    VAR CurrentState = 'Table'[ChangeState]

    VAR PervVariationRT = 
        SUMX(
            FILTER(
                'Table',
                'Table'[ChangeState] < CurrentState
            ),
            'Table'[ChargeVariation]
        )

    VAR Result =
        MIN(CurrentVariation + MIN(PervVariationRT, UpperBound), UpperBound) + IF(CurrentState = MAX('Table'[ChangeState]), CurrentVariation)

    RETURN
        Result

Это дает мне следующие результаты:

Если вы расширите выборку данных, включив в нее больше нарушений, это не совсем сработает.

davidebacci 07.08.2024 16:05

Это работает:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlRQ0lEyN4CQSrE60UpGILauKYg0MwWLGIPYRmA1FhA1JmA1hsjaTDG0mYF1ITSZQ/QgtFigKbAEmwCSBxoQCwA = ", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ChangeState = _t, ChargeVariation = _t, ResidualCapacity = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"ChangeState", Int64.Type}, {"ChargeVariation", Int64.Type}, {"ResidualCapacity", Int64.Type}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "Custom", each 
        let a =Table.SelectRows(#"Changed Type", (x)=> x[ChangeState] < [ChangeState])[ChargeVariation],
        b = List.Accumulate(a, 0, 
        (state, current ) => if  current + state > 80 then 80 else current + state 
        )
        in List.Min( {b + [ChargeVariation], 80}))
in
    #"Added Custom"

DAX — не самое чистое решение, однако попробуйте создать два вычисляемых столбца в следующем порядке:

rowDiff = 
  var thisState = [ChangeState]
  var diff = 
    SUMX(
      FILTER('Table', [ChangeState] <= thisState),
      [ChargeVariation]
    )
  return IF(diff > 80, diff - 80)


ResidualCapacity = 
  var thisState = [ChangeState]
  var maxDelta = 
    MAXX(
      FILTER('Table', [ChangeState] <= thisState),
      [rowDiff]
    )
  var ss = 
    SUMX(
      FILTER('Table', [ChangeState] <= thisState),
      [ChargeVariation]
    )
  return ss - maxDelta

Это текущая проблема с изюминкой.

В Power Query другим подходом было бы использование функции List.Generate для создания списка итогов, а затем использование Table.FromColumns для объединения его с исходной таблицей.

Преимущество этого подхода состоит в том, что можно избежать Table.SelectRows, что может потребовать больших ресурсов и времени.

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUTI3UIrViVYyAjJ1TcFMYyDTCCJqAhI1hLBNoSpiAQ= = ", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ChangeState = _t, ChargeVariation = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"ChangeState", Int64.Type}, {"ChargeVariation", Int64.Type}}),
    
    #"Add Residual Capacity" = Table.FromColumns(
        Table.ToColumns(#"Changed Type")
        & {List.Generate(
        ()=>[rt=#"Changed Type"[ChargeVariation]{0}, idx=0],
        each [idx]<Table.RowCount(#"Changed Type"),
        each [rt = List.Min({80, [rt] + #"Changed Type"[ChargeVariation]{[idx]+1}}), idx=[idx]+1],
        each [rt])}, type table[ChangeState=Int64.Type, ChargeVariation=Int64.Type, ResidualCapacity=Int64.Type])
in
    #"Add Residual Capacity"

Ответ принят как подходящий

Отказ от ответственности: я получил решение от сообщества Fabric. Вот ссылка на решение.

Для тех, кому интересно, ниже приведены комментарии к различным решениям, протестированным между решениями, полученными здесь, на Stack Overflow, и решениями от сообщества Fabric.

Как я упоминал в сообществе Fabric в ответ на решение Greg_Deckler, реальная таблица состоит из 61 тыс. строк, разделенных на разные пропорции по 16 различным идентификаторам, и структурирована следующим образом:

ИДЕНТИФИКАТОР Индекс Ценить А 1 ... А ... ... А Н ... --- --- --- П 1 ... П ... ... П Н ...

Я протестировал различные предложенные коды и вот мои комментарии:

  • Решения, полученные при переполнении стека:

    • Решение DAX @Sam_Nseir: первый вычисляемый столбец генерируется примерно за 3 минуты, но второй обходится намного дороже, и я получаю ошибку «Недостаточно памяти для завершения этой операции».
    • Сравнение решения Power Query между @Ron_Rosenfeld и @davidebacci: во время выполнения размер входной таблицы Рона растет намного быстрее, чем у Давиде, но оба значительно увеличивают размер входной таблицы. Примерно через 10 минут вычислений предложенное Роном решение достигло 30 ГБ памяти, а решение Давиде — около 7 ГБ.
  • Решения от сообщества Fabric:

    • Greg_Deckler: Предложил решение DAX, которое генерирует ошибку «Недостаточно памяти для завершения этой операции».
    • ОуэнОгер: Предложил оптимальное решение. Я протестировал код DAX и после трех минут запроса получил ожидаемый результат.

Другие вопросы по теме

Похожие вопросы

Expression.Error — мы не можем преобразовать значение типа Function в тип List
Преобразование символов в дату и получение данных за последние два года
Извлеките дату начала и окончания отпуска по болезни в запросе мощности (пробелы и острова)
Игнорирование ошибки в Table.ExpandTableColumn или автоматическая замена на ноль
Как связать Power BI с рабочей областью Azure Log Analytics для анализа данных из LAW в Power BI?
Среднее время цикла в моем коде Python и виджете «Время цикла» различается
Как подсчитать, имеет ли ваш столбец одинаковые значения в другом столбце в отдельной связанной таблице
«Исключение: отчет Power BI не встроен» в Azure Databricks
Создайте столбец, который будет учитывать все буквы «Y» во всех остальных столбцах для каждой строки в Power BI
Как в Power Query рассчитать общее время, отработанное за несколько дней, на основе графика рабочих смен и без учета выходных?