Approach:Replace nested EARLIER/EARLIEST row-context tricks with VAR to capture values once, and use table functions (FILTER, ADDCOLUMNS, RANKX) that work in filter-context. This removes repeated row-context iteration, improves readability, and often gives better performance.Original (using EARLIER) — computes running rank per Category by SalesAmount:dax
RunningRank_Earlier =
SUMX(
FILTER(
Sales,
Sales[Category] = EARLIER(Sales[Category]) &&
(Sales[SalesDate] < EARLIER(Sales[SalesDate]) ||
(Sales[SalesDate] = EARLIER(Sales[SalesDate]) && Sales[SalesID] <= EARLIER(Sales[SalesID])))
),
1
)
Refactored (using VAR + RANKX for clarity and efficiency):dax
RunningRank_VAR =
VAR CurrentCategory = Sales[Category]
VAR CurrentDate = Sales[SalesDate]
VAR CurrentID = Sales[SalesID]
VAR CategoryTable =
FILTER(
ALL(Sales),
Sales[Category] = CurrentCategory
)
VAR Ranked =
RANKX(
CategoryTable,
// tie-breaker: date then ID to make deterministic ordering
Sales[SalesDate] + Sales[SalesID] / 1000000,
CurrentDate + CurrentID / 1000000,
ASC,
DENSE
)
RETURN
Ranked
Key points / reasoning:- VAR captures current row values once, avoiding nested EARLIER calls which are hard to read.- ALL(Sales) in CategoryTable ensures RANKX evaluates over the full category regardless of existing row-context filters; adjust depending on desired behavior.- Using RANKX delegates iteration to an optimized engine function, clearer intent (rank) and usually faster than manual SUMX+FILTER loops.- Tie-breaker numeric expression ensures deterministic ordering; adjust precision as needed.Performance & maintainability:- Readability: variables name intent (CurrentCategory/CurrentDate) versus multiple EARLIER calls.- Performance: RANKX and using VAR to limit filter scope reduces repeated evaluation; avoids nested row-context which can cause complex evaluation paths.- Edge cases: duplicate dates—use stable tie-breaker; very large tables—consider pre-aggregating or creating indexed lookup tables.- Alternatives: ADDCOLUMNS + RANKX on a summarized table (SUMMARIZE/ADDCOLUMNS) if you need ranking at an aggregate grain instead of row-level.