У меня есть набор данных, представляющий изменения состояния батареи, и мне нужно вычислить ResidualCapacity
для каждого изменения состояния. ResidualCapacity
следует рассчитывать как предыдущий ResidualCapacity
плюс текущий ChargeVariation
, не превышая UpperBound
, равного 80.
Вот структура моей таблицы с правильным **ResidualCapacity
**значением:
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 Да, решение для запроса мощности тоже подходит
Не забудьте отметить решение как решенное и проголосовать, если решение помогло. Спасибо
Не могли бы вы просто изменить выражение «Результат», чтобы проверить, равно ли текущее состояние изменения максимальному состоянию изменения таблицы, и добавить соответствующий вариант оплаты, если да?
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
Это дает мне следующие результаты:
Если вы расширите выборку данных, включив в нее больше нарушений, это не совсем сработает.
Это работает:
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 различным идентификаторам, и структурирована следующим образом:
Я протестировал различные предложенные коды и вот мои комментарии:
Решения, полученные при переполнении стека:
Решения от сообщества Fabric:
Согласитесь ли вы на решение запроса мощности?