Nesting SELECT() expressions (putting SELECT() expressions within SELECT() expressions) is computationally expensive and potentially (very!) inefficient. Performance degrades very fast as the data set grows. In general, nested SELECT() expressions should be avoided as a best practice.
Your expression contains:
-
A FILTER("Main Data", ...) expression (a form of SELECT()) that inspects every row of the Main Data table.
-
A MIN(SELECT(Main Data[_RowNumber], ...)) expression that also inspects every row of Main Data for every row inspected by (1).
-
A LOOKUP(...) expression (also a form of SELECT()) that inspects every row of Session for every row inspected by (2).
-
A MAX(SELECT(Main Data[_RowNumber], ...)) expression that also inspects every row of Main Data for every row of (2).
-
Another LOOKUP(...) expression that inspects every row of Session for every row of (4).
-
Another MAX(SELECT(Main Data[_RowNumber], ...)) expression that also inspects every row of Main Data for every row of (1) in the worst case.
-
Yet another LOOKUP(...) expression that inspects every row of Session for every row in (6).
Each of those “for every row” is a multiplier to the number of operations done. The more operations, the slower your app runs.
Suppose Main Data contains 100 rows and Sessions contains 10 rows. Based on the above analysis, in the best case, your FILTER() expression examines (100 + (100 * 100) + (100 * 100 * 10) + (100 * 100 * 100) + (100 * 100 * 100 * 10)) = (100 + 10000 + 100000 + 1000000 + 10000000) = 11,110,100 rows.
In the worst case, your FILTER() expression examines (100 + (100 * 100) + (100 * 100 * 10) + (100 * 100 * 100) + (100 * 100 * 100 * 10) + (100 * 100) + (100 * 100 * 10)) = (100 + 10000 + 100000 + 1000000 + 10000000 + 10000 + 100000) = 11,220,100 rows.
Ideally, any repeated SELECT() expression would be moved to its own virtual column where it will be evaluated only once. A reference to the virtual column would then replace the snippet in the larger expression.
My proposed LOOKUP() expression occurs three times in your FILTER() expression. If we move it to its own virtual column (e.g., lookup_session_number) and replace every occurrence of my LOOKUP(...) with [lookup_session_number], it reduces the worst case to (10 + 100 + (100 * 100) + (100 * 100 * 100) + (100 * 100)) = (10 + 100 + 10000 + 1000000 + 10000) = 1,020,110 row examinations.
The MAX(SELECT(Main Data[_RowNumber], ...)) expression occurs twice. If we also move that to a max_rownumber virtual column, the total worst case count goes down to (10 + 100 + 100 + (100 * 100)) = (10 + 100 + 100 + 10000) = 10,210 row examinations.
MAX(
SELECT(
Main Data[_RowNumber],
(
[Start at session no]
<= [_THISROW].[lookup_session_number]
)
)
)
The MIN(SELECT(Main Data[_RowNumber], ...)) expression occurs only once within the FILTER() expression, but that still means it gets evaluated once for every row FILTER() examines. If we move it to min_rownumber, the worst case bottoms out at (10 + 100 + 100 + 100) = 310 row examinations, down from 11,220,100!
MIN(
SELECT(
Main Data[_RowNumber],
AND(
(
[Start at session no]
<> (
[_THISROW].[lookup_session_number]
+ (
[_RowNumber]
+ (3 - 1)
- [_THISROW].[max_rownumber]
)
/ 3
)
)
),
(
[_RowNumber]
> [_THISROW].[max_rownumber]
)
)
)
)