The function makes three sort operation and sums the result for each of the rows in the source table (Movements).
Even though the rows are grouped and aggregated in the movements table, this results in many filtering steps and is expensive.
Is there a better way?
SelectBalanceFromMovements(,,):
(TrYrPr as number,
ProdNo as number,
StorageNo as number) =>
let
Source = Table.SelectRows(Movements, each [TransYearPeriod] < TrYrPr),
Step1 = Table.SelectRows(Source, each [ProdNo] = ProdNo),
Step2 = Table.SelectRows(Step1, each [StorageNumber] = StorageNo),
Step3 = Table.Group(Step2, {"ProdNo", "StorageNumber"}, {{"Balance", each List.Sum([Movement]), type number}}),
Step4 = Table.AddColumn(Step3, "TransYearPeriod", each TrYrPr)
in
Step4
Edits:
Changed by suggestion from greggyb of combining the filter steps, and I did not need the period column:
(TrYrPr as number,
ProdNo as number,
StorageNo as number) =>
let
Step1 = Table.SelectRows(Movements, each [StorageNumber] = StorageNo and [ProdNo] = ProdNo and [TransYearPeriod] < TrYrPr),
Step2 = Table.Group(Step1, {"ProdNo", "StorageNumber"}, {{"Balance", each List.Sum([Movement]), type number}})
in
Step2
These changes did not noticeably change performance.
The output is correct and effective, however not very efficient.
I believe the slow processing comes not from the aggregation, but rather creating multiple copies of the data in memory during the filter.
This function runs 1 time per row in a reference of my source table Movements, and there are 380 rows.
Is there a way to speed up? Is it possible to use DAX instead?
Edit: The calling of the function:
#"Invoked Custom Function" = Table.AddColumn(#"Removed Columns", "SelectBalanceFromMovements", each SelectBalanceFromMovements([TransYearPeriod], [ProdNo], [StorageNumber])),
#"Expanded SelectBalanceFromMovements" = Table.ExpandTableColumn(#"Invoked Custom Function", "SelectBalanceFromMovements", {"Balance"}, {"SelectBalanceFromMovements.Balance"}),
Table.SelectRows
instead of 3 successive ones. You can logically AND withand
in a single filtering step referring to all 3columns. You could also merge yourStep3
andStep4
by defining a second column in yourTable.Group
whose logic is{"TransYearPeriod", each TrYrPr}
. – greggybTable.Buffer
and your lists inList.Buffer
. Buffer puts your data into memory. Also turn off background refreshes, if it is currently enabled. These are good posts with a lot of ways to improve performance. thebiccountant.com/speedperformance-aspects adatis.co.uk/buffer-m-function-in-query-editor-power-bi – Jenn