Power BI Desktop DAX 重启 运行 列总计
Power BI Desktop DAX restart running total column
我有一个 table,每个人都有一年中每一天的记录。我使用此函数根据每日余额列
实现了 运行 总计
CALCULATE(
SUM(Leave[Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Employee Id]),
Leave[Date] <= EARLIER(Leave[Date])
))
但我需要 运行 总数从 1 重新开始,如果类型 = 工作并且 运行 每日余额总数小于零并且前一行的类型不等于工作.下面是来自 Excel 的屏幕截图。所需的功能栏是我需要得到的。
花了一段时间,但我想出了一个解决方法。假设,空白的余额值始终为 -1,"Working" 的值为 1,并且该数据可用于所有日期而没有间隔,类似下面的计算可能有效:
Running Total =
VAR Employee = Leave[Employee ID]
VAR Date1 = Leave[Date]
VAR Prev_Blank = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]=BLANK()))
VAR Day_count_Working = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] > Prev_Blank),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]="Working"))
VAR Day_count = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] >= Prev_Blank),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee))
RETURN (IF(Day_count_Working=BLANK(),Day_count,Day_count-1)-Day_count_Working)*-1 + Day_count_Working
请记住,这可能不是成品,因为我使用的是一个小样本,但这应该可以帮助您入门。希望这有帮助。
计算有点冗长,但它似乎适用于我使用的示例数据。试一试:
Running Total =
VAR Employee = Leave[Employee ID]
VAR Date1 = Leave[Date]
VAR Prev_Blank = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]=BLANK()))
VAR Prev_Working = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]="Working"))
VAR Prev_Blank1 = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Prev_Working),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]=BLANK()))
VAR Prev_type = CALCULATE(MAX(Leave[Type]),
FILTER(Leave,Leave[Date] = Date1-1),
FILTER(Leave,Leave[Employee ID]=Employee))
VAR Prev_Blank2 = IF(Leave[Type]="Working" && (Prev_Blank1=BLANK() || Prev_type=BLANK()),Date1-1,Prev_Blank1)
VAR Day_count_Working = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] > Prev_Blank2),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]="Working"))
VAR Day_count = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] >= Prev_Blank2),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee))
RETURN (IF(Day_count_Working=BLANK(),Day_count,Day_count-1)-Day_count_Working)*-1 + Day_count_Working
我在这里使用了一堆变量。您也许可以想出一个较短的版本。基本上这个想法是找到之前第一次出现的 "Working" 来找到从哪里开始计算。这是在变量 "Prev_Blank2" 中计算的。一旦我们知道起点(这里从 1 开始),那么我们可以简单地计算 Prev_Blank2 和当前记录日期之间用 "Working" 或 blank() 的天数。利用这些天数,我们可以 return 总计 运行 的最终值。
希望这能奏效 ;)
希望您下次粘贴生成示例数据而不是图片的 csv 或代码。 :)
我只是建议您改用 PowerQuery 进行计算。
我尝试将代码拆分几个步骤以提高可读性。
这可能看起来有点复杂,但效果很好。只需将其粘贴到高级编辑器中,然后用您的源数据替换源。
祝你好运!
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjDUMzDSMzIwtFTSUQpILSrOz1MwBDLL84uyM/PSlWJ1gGqMsKuBSBrjkzQhwnRTItSYEaHGHJ9DLPBJWhI23dAAjwGGOAIRIokj9OCmxwIA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [date = _t, name = _t, #"type" = _t]),
SetTypes = Table.TransformColumnTypes(Source,{{"date", type date}, {"name", type text}, {"type", type text}}),
TempColumn1 = Table.AddColumn(SetTypes, "LastOtherType", (row)=>List.Max(Table.SelectRows(SetTypes, each ([name] = row[name] and [type] <> row[type] and [date] <= row[date]))[date], row[date]), type date) //Here for each row we select all rows of other type with earlier date, and take max that date. Thus we know when was previous change from one type to another
//Here for each row we select all rows of other type with earlier date, and take max that date. Thus we know when was previous change from one type to another
,
TempColumn2 = Table.AddColumn(TempColumn1, "Count", (row)=>
(if row[type]="working" then 1 else -1) *
Table.RowCount(
Table.SelectRows(SetTypes, each ([name] = row[name] and [type] = row[type] and [date] <= row[date] and [date] > row[LastOtherType])) /* select all rows between type change (see prev step) and current row */
), /*and count them*/
Int64.Type) // finally multiply -1 if they are not working type
,
FinalColumn = Table.AddColumn(TempColumn2, "FinalFormula", (row)=>
(if row[type] = "working" then row[Count] else /* for working days use Count, for others take prev max Count and add current Count, which is negative for non-working*/
Table.LastN(Table.SelectRows(TempColumn2, each [name] = row[name] and [type] = "working" and [LastOtherType] <= row[LastOtherType]),1)[Count]{0}
+ row[Count])
, Int64.Type),
RemovedTempColumns = Table.RemoveColumns(FinalColumn,{"LastOtherType", "Count"})
in
RemovedTempColumns
概览
要求 PowerBI 完成这项工作具有挑战性,因此可能很难找到整洁的方法。
最大的问题是 PowerBI 的数据模型不支持 运行 计数的概念——至少不支持我们在 Excel 中使用的方式。在 Excel 中,一列可以引用同一列“上一行”中出现的值,然后通过不同列中列出的一些“每日变化”进行调整。
PowerBI 只能通过将某些行子集的所有每日更改相加来模仿这一点。我们获取当前行中的日期值并创建一个过滤的 table,其中所有日期都小于当前行的日期,然后总结该子集中的所有每日变化。这似乎是一个细微的差别,但它是相当重要的:
这意味着无法“覆盖”我们的 运行 总数。唯一正在做的数学计算发生在包含每日变化的列上——包含“运行 total”的列只是一个结果——它永远不会用于任何后续行的计算。
我们必须放弃“重置”的概念,而是想象制作一个包含“调整”值的列。我们的调整将是一个可以包含的值,以便在满足所描述的条件时,每日余额和调整的总和将为 1。
如果我们查看 OP 给出的 运行 计算值,我们会发现在“工作”日之前的“非工作日”,我们的 运行 总值给了我们所需的金额,如果逆转,总和为零,并导致 运行 总数在接下来的每个工作日增加一个。这是我们想要的行为(有一个问题将在后面描述)。
结果
Most Recent Date Prior to Work =
CALCULATE(
Max(Leave[Date]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] = EARLIER(Leave[Date]) -1 && Leave[Type] <> "Working" && Earlier(Leave[Type]) = "Working"
))
这有助于了解行上下文和过滤器上下文之间的区别以及 EARLIER 如何操作以遵循此计算。在这种情况下,您可以认为 "EARLIER" 的意思是“此引用指向当前行中的值”,否则引用指向 "ALLEXCEPT(Leave, Leave[Id])." 返回的整个 table 以这种方式,我们找到当前行的类型为 "Working" 而前一天的行的类型为其他类型的地方。
Most Recent Date Prior to Work Complete =
CALCULATE(
Max(Leave[Most Recent Date Prior to Work]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] <= EARLIER(Leave[Date])
))
此计算模仿了一种 'fill down' 操作。它说,"When looking at all the rows whose date is before the date on THIS row, return the biggest value in 'Most Recent Date Prior to Work."
Daily Balance Adjustment =
CALCULATE(
SUM(Leave[Running Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] = EARLIER(Leave[Most Recent Date Prior to Work Complete])
))
现在每一行都有一个字段说明去哪里找到每日余额以用作我们的调整,我们可以从 table.
中查找它
Adjusted Daily Balance = Leave[Running Daily Balance] - Leave[Daily Balance Adjustment]
最后,我们将调整应用到我们的 运行 总数以获得最终结果。
问题
此方法无法解决计数不应重置的问题,除非 运行 每日余额低于零。我之前被证明是错误的,但我会说这不能单独在 DAX 中完成,因为它会创建循环依赖。本质上,您提出了一个要求:使用聚合值来确定聚合中应包含的内容。
这就是我能带给你的。希望对你有帮助。
我想我有!
这是基于我之前发布的解决方案的结果:(数据已被修改以展示更多 "work / no work" 行为和用例)
结果
详情
(1) 删除 "Adjusted Running Daily Balance" 和 "Daily Balance Adjustment" 列。稍等片刻,我们将得到相同的结果。
(2) 创建以下列(RDB = "running daily balance")...
Grouped RDB =
CALCULATE(
SUM(Leave[Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Id], Leave[Most Recent Date Prior to Work Complete]),
Leave[Date] <= EARLIER(Leave[Date])
))
创建 "Most Recent Date Prior to Work Complete," 之后,我们实际上拥有了完成我声称以前不可能完成的 'reset' 所需的部分。通过对该字段进行过滤,我们有机会从“1”开始每个切片
(3) 我们仍然遇到同样的问题,我们无法查看专栏中的结果并使用它来决定稍后在同一专栏中做什么。但是我们可以构建一个新的调整列来保存该信息!我们已经有了对 'Most Recent Date Prior to Work' 的引用——那是前一组的最后一天……包含我们需要的信息的行!
Grouped RDB Adjustment =
VAR CalculatedAdjustment =
CALCULATE(
SUM(Leave[Grouped RDB]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] IN SELECTCOLUMNS(
FILTER(
Leave,
Leave[Most Recent Date Prior to Work] <> BLANK() &&
Leave[id] = EARLIER(Leave[Id])), "MRDPtW", Leave[Most Recent Date Prior to Work]) &&
Leave[Most Recent Date Prior to Work Complete] < EARLIER(Leave[Most Recent Date Prior to Work Complete]) &&
Leave[Most Recent Date Prior to Work Complete] <> Blank()
))
RETURN if (CalculatedAdjustment > 0, CalculatedAdjustment, 0)
所以我们查看 Each 前一组的最后一天,如果这些调整的总和具有正值,我们应用它,如果它是负值,我们不理会它.此外,如果我们的人的前几天是非工作日,我们根本不希望在我们的调整中出现最初的负面影响,因此它也会被过滤掉。
(4) 这最后一步会将调整带入最终结果。总结这两个新列,我们最终应该得到调整后的 运行 每日余额。瞧!
Adjusted Running Daily Balance = Leave[Grouped RDB] + Leave[Grouped RDB Adjustment]
我们在获得此结果的过程中构建了很多额外的列,这通常不是我最喜欢做的事情。但是,这是一个棘手的问题。
这不仅是一个带有条件的 运行 总计,而且也是一个 nested/clustered 总计,因为逻辑必须应用于 ID 级别。对于大型表,M 比 DAX 更擅长,因为它不使用那么多 RAM。 (我在这里写了博客:Link to Blogpost
以下函数使该逻辑适应当前情况并且必须应用于 ID 级别:(所需的列名称为:"Type"、"Daily Allowance"、"Adjustments")
(MyTable as table) =>
let
SelectJustWhatsNeeded = Table.SelectColumns(MyTable,{"Type", "Daily Allowance", "Adjustments"}),
ReplaceNulls = Table.ReplaceValue(SelectJustWhatsNeeded,null,0,Replacer.ReplaceValue,{"Adjustments"}),
#"Merged Columns" = Table.CombineColumns(ReplaceNulls,{"Daily Allowance", "Adjustments"}, List.Sum,"Amount"),
TransformToList = List.Buffer(Table.ToRecords(#"Merged Columns")),
ConditionalRunningTotal = List.Skip(List.Generate(
() => [Type = TransformToList{0}[Type], Result = 0, Counter = 0],
each [Counter] <= List.Count(TransformToList),
each [
Result = if TransformToList{[Counter]}[Type] = "working" and [Result] < 0 and [Type] <> "working"
then TransformToList{[Counter]}[Amount]
else TransformToList{[Counter]}[Amount] + [Result] ,
Type = TransformToList{[Counter]}[Type],
Counter = [Counter] + 1
],
each [Result]
)),
Custom1 = Table.FromColumns( Table.ToColumns(MyTable) & {ConditionalRunningTotal}, Table.ColumnNames(MyTable) & {"Result"} )
in
Custom1
我有一个 table,每个人都有一年中每一天的记录。我使用此函数根据每日余额列
实现了 运行 总计CALCULATE(
SUM(Leave[Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Employee Id]),
Leave[Date] <= EARLIER(Leave[Date])
))
但我需要 运行 总数从 1 重新开始,如果类型 = 工作并且 运行 每日余额总数小于零并且前一行的类型不等于工作.下面是来自 Excel 的屏幕截图。所需的功能栏是我需要得到的。
花了一段时间,但我想出了一个解决方法。假设,空白的余额值始终为 -1,"Working" 的值为 1,并且该数据可用于所有日期而没有间隔,类似下面的计算可能有效:
Running Total =
VAR Employee = Leave[Employee ID]
VAR Date1 = Leave[Date]
VAR Prev_Blank = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]=BLANK()))
VAR Day_count_Working = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] > Prev_Blank),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]="Working"))
VAR Day_count = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] >= Prev_Blank),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee))
RETURN (IF(Day_count_Working=BLANK(),Day_count,Day_count-1)-Day_count_Working)*-1 + Day_count_Working
请记住,这可能不是成品,因为我使用的是一个小样本,但这应该可以帮助您入门。希望这有帮助。
计算有点冗长,但它似乎适用于我使用的示例数据。试一试:
Running Total =
VAR Employee = Leave[Employee ID]
VAR Date1 = Leave[Date]
VAR Prev_Blank = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]=BLANK()))
VAR Prev_Working = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]="Working"))
VAR Prev_Blank1 = CALCULATE(MAX(Leave[Date]),
FILTER(Leave,Leave[Date] < Prev_Working),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]=BLANK()))
VAR Prev_type = CALCULATE(MAX(Leave[Type]),
FILTER(Leave,Leave[Date] = Date1-1),
FILTER(Leave,Leave[Employee ID]=Employee))
VAR Prev_Blank2 = IF(Leave[Type]="Working" && (Prev_Blank1=BLANK() || Prev_type=BLANK()),Date1-1,Prev_Blank1)
VAR Day_count_Working = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] > Prev_Blank2),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee),
FILTER(Leave,Leave[Type]="Working"))
VAR Day_count = CALCULATE(COUNT(Leave[Date]),
FILTER(Leave,Leave[Date] >= Prev_Blank2),
FILTER(Leave,Leave[Date] <= Date1),
FILTER(Leave,Leave[Employee ID]=Employee))
RETURN (IF(Day_count_Working=BLANK(),Day_count,Day_count-1)-Day_count_Working)*-1 + Day_count_Working
我在这里使用了一堆变量。您也许可以想出一个较短的版本。基本上这个想法是找到之前第一次出现的 "Working" 来找到从哪里开始计算。这是在变量 "Prev_Blank2" 中计算的。一旦我们知道起点(这里从 1 开始),那么我们可以简单地计算 Prev_Blank2 和当前记录日期之间用 "Working" 或 blank() 的天数。利用这些天数,我们可以 return 总计 运行 的最终值。
希望这能奏效 ;)
希望您下次粘贴生成示例数据而不是图片的 csv 或代码。 :)
我只是建议您改用 PowerQuery 进行计算。 我尝试将代码拆分几个步骤以提高可读性。 这可能看起来有点复杂,但效果很好。只需将其粘贴到高级编辑器中,然后用您的源数据替换源。 祝你好运!
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjDUMzDSMzIwtFTSUQpILSrOz1MwBDLL84uyM/PSlWJ1gGqMsKuBSBrjkzQhwnRTItSYEaHGHJ9DLPBJWhI23dAAjwGGOAIRIokj9OCmxwIA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [date = _t, name = _t, #"type" = _t]),
SetTypes = Table.TransformColumnTypes(Source,{{"date", type date}, {"name", type text}, {"type", type text}}),
TempColumn1 = Table.AddColumn(SetTypes, "LastOtherType", (row)=>List.Max(Table.SelectRows(SetTypes, each ([name] = row[name] and [type] <> row[type] and [date] <= row[date]))[date], row[date]), type date) //Here for each row we select all rows of other type with earlier date, and take max that date. Thus we know when was previous change from one type to another
//Here for each row we select all rows of other type with earlier date, and take max that date. Thus we know when was previous change from one type to another
,
TempColumn2 = Table.AddColumn(TempColumn1, "Count", (row)=>
(if row[type]="working" then 1 else -1) *
Table.RowCount(
Table.SelectRows(SetTypes, each ([name] = row[name] and [type] = row[type] and [date] <= row[date] and [date] > row[LastOtherType])) /* select all rows between type change (see prev step) and current row */
), /*and count them*/
Int64.Type) // finally multiply -1 if they are not working type
,
FinalColumn = Table.AddColumn(TempColumn2, "FinalFormula", (row)=>
(if row[type] = "working" then row[Count] else /* for working days use Count, for others take prev max Count and add current Count, which is negative for non-working*/
Table.LastN(Table.SelectRows(TempColumn2, each [name] = row[name] and [type] = "working" and [LastOtherType] <= row[LastOtherType]),1)[Count]{0}
+ row[Count])
, Int64.Type),
RemovedTempColumns = Table.RemoveColumns(FinalColumn,{"LastOtherType", "Count"})
in
RemovedTempColumns
概览
要求 PowerBI 完成这项工作具有挑战性,因此可能很难找到整洁的方法。
最大的问题是 PowerBI 的数据模型不支持 运行 计数的概念——至少不支持我们在 Excel 中使用的方式。在 Excel 中,一列可以引用同一列“上一行”中出现的值,然后通过不同列中列出的一些“每日变化”进行调整。
PowerBI 只能通过将某些行子集的所有每日更改相加来模仿这一点。我们获取当前行中的日期值并创建一个过滤的 table,其中所有日期都小于当前行的日期,然后总结该子集中的所有每日变化。这似乎是一个细微的差别,但它是相当重要的:
这意味着无法“覆盖”我们的 运行 总数。唯一正在做的数学计算发生在包含每日变化的列上——包含“运行 total”的列只是一个结果——它永远不会用于任何后续行的计算。
我们必须放弃“重置”的概念,而是想象制作一个包含“调整”值的列。我们的调整将是一个可以包含的值,以便在满足所描述的条件时,每日余额和调整的总和将为 1。
如果我们查看 OP 给出的 运行 计算值,我们会发现在“工作”日之前的“非工作日”,我们的 运行 总值给了我们所需的金额,如果逆转,总和为零,并导致 运行 总数在接下来的每个工作日增加一个。这是我们想要的行为(有一个问题将在后面描述)。
结果
Most Recent Date Prior to Work =
CALCULATE(
Max(Leave[Date]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] = EARLIER(Leave[Date]) -1 && Leave[Type] <> "Working" && Earlier(Leave[Type]) = "Working"
))
这有助于了解行上下文和过滤器上下文之间的区别以及 EARLIER 如何操作以遵循此计算。在这种情况下,您可以认为 "EARLIER" 的意思是“此引用指向当前行中的值”,否则引用指向 "ALLEXCEPT(Leave, Leave[Id])." 返回的整个 table 以这种方式,我们找到当前行的类型为 "Working" 而前一天的行的类型为其他类型的地方。
Most Recent Date Prior to Work Complete =
CALCULATE(
Max(Leave[Most Recent Date Prior to Work]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] <= EARLIER(Leave[Date])
))
此计算模仿了一种 'fill down' 操作。它说,"When looking at all the rows whose date is before the date on THIS row, return the biggest value in 'Most Recent Date Prior to Work."
Daily Balance Adjustment =
CALCULATE(
SUM(Leave[Running Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] = EARLIER(Leave[Most Recent Date Prior to Work Complete])
))
现在每一行都有一个字段说明去哪里找到每日余额以用作我们的调整,我们可以从 table.
中查找它Adjusted Daily Balance = Leave[Running Daily Balance] - Leave[Daily Balance Adjustment]
最后,我们将调整应用到我们的 运行 总数以获得最终结果。
问题
此方法无法解决计数不应重置的问题,除非 运行 每日余额低于零。我之前被证明是错误的,但我会说这不能单独在 DAX 中完成,因为它会创建循环依赖。本质上,您提出了一个要求:使用聚合值来确定聚合中应包含的内容。
这就是我能带给你的。希望对你有帮助。
我想我有!
这是基于我之前发布的解决方案的结果:(数据已被修改以展示更多 "work / no work" 行为和用例)
结果
详情
(1) 删除 "Adjusted Running Daily Balance" 和 "Daily Balance Adjustment" 列。稍等片刻,我们将得到相同的结果。
(2) 创建以下列(RDB = "running daily balance")...
Grouped RDB =
CALCULATE(
SUM(Leave[Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Id], Leave[Most Recent Date Prior to Work Complete]),
Leave[Date] <= EARLIER(Leave[Date])
))
创建 "Most Recent Date Prior to Work Complete," 之后,我们实际上拥有了完成我声称以前不可能完成的 'reset' 所需的部分。通过对该字段进行过滤,我们有机会从“1”开始每个切片
(3) 我们仍然遇到同样的问题,我们无法查看专栏中的结果并使用它来决定稍后在同一专栏中做什么。但是我们可以构建一个新的调整列来保存该信息!我们已经有了对 'Most Recent Date Prior to Work' 的引用——那是前一组的最后一天……包含我们需要的信息的行!
Grouped RDB Adjustment =
VAR CalculatedAdjustment =
CALCULATE(
SUM(Leave[Grouped RDB]),
FILTER(
ALLEXCEPT(Leave, Leave[Id]),
Leave[Date] IN SELECTCOLUMNS(
FILTER(
Leave,
Leave[Most Recent Date Prior to Work] <> BLANK() &&
Leave[id] = EARLIER(Leave[Id])), "MRDPtW", Leave[Most Recent Date Prior to Work]) &&
Leave[Most Recent Date Prior to Work Complete] < EARLIER(Leave[Most Recent Date Prior to Work Complete]) &&
Leave[Most Recent Date Prior to Work Complete] <> Blank()
))
RETURN if (CalculatedAdjustment > 0, CalculatedAdjustment, 0)
所以我们查看 Each 前一组的最后一天,如果这些调整的总和具有正值,我们应用它,如果它是负值,我们不理会它.此外,如果我们的人的前几天是非工作日,我们根本不希望在我们的调整中出现最初的负面影响,因此它也会被过滤掉。
(4) 这最后一步会将调整带入最终结果。总结这两个新列,我们最终应该得到调整后的 运行 每日余额。瞧!
Adjusted Running Daily Balance = Leave[Grouped RDB] + Leave[Grouped RDB Adjustment]
我们在获得此结果的过程中构建了很多额外的列,这通常不是我最喜欢做的事情。但是,这是一个棘手的问题。
这不仅是一个带有条件的 运行 总计,而且也是一个 nested/clustered 总计,因为逻辑必须应用于 ID 级别。对于大型表,M 比 DAX 更擅长,因为它不使用那么多 RAM。 (我在这里写了博客:Link to Blogpost
以下函数使该逻辑适应当前情况并且必须应用于 ID 级别:(所需的列名称为:"Type"、"Daily Allowance"、"Adjustments")
(MyTable as table) =>
let
SelectJustWhatsNeeded = Table.SelectColumns(MyTable,{"Type", "Daily Allowance", "Adjustments"}),
ReplaceNulls = Table.ReplaceValue(SelectJustWhatsNeeded,null,0,Replacer.ReplaceValue,{"Adjustments"}),
#"Merged Columns" = Table.CombineColumns(ReplaceNulls,{"Daily Allowance", "Adjustments"}, List.Sum,"Amount"),
TransformToList = List.Buffer(Table.ToRecords(#"Merged Columns")),
ConditionalRunningTotal = List.Skip(List.Generate(
() => [Type = TransformToList{0}[Type], Result = 0, Counter = 0],
each [Counter] <= List.Count(TransformToList),
each [
Result = if TransformToList{[Counter]}[Type] = "working" and [Result] < 0 and [Type] <> "working"
then TransformToList{[Counter]}[Amount]
else TransformToList{[Counter]}[Amount] + [Result] ,
Type = TransformToList{[Counter]}[Type],
Counter = [Counter] + 1
],
each [Result]
)),
Custom1 = Table.FromColumns( Table.ToColumns(MyTable) & {ConditionalRunningTotal}, Table.ColumnNames(MyTable) & {"Result"} )
in
Custom1