Evaluation Contexts
Evaluation Contexts
So now that know how to use iterators, it's time for a little review. You can get away with not having a complete understanding of them and still use them pretty successfully for a while, but often iterators can still be confusing, even after the first explanation. To really get a good understanding , we are going to have to review filter context and row context and understand the difference.
Evaluation Contexts define what values an expression can see.
Evaluation contexts sounds fancy, like some calculus term, but what they really boil down is what rows can an expression see when it's evaluated and what context is it being computed?. The rest is just a matter of understanding what can manipulate and change these contexts.
Filter Context vs. Row Context
Filter Context
Filter Context is a combination of the visual filters and user filters.
We went over this when we dealt with the CALCULATE function. It's all the implied filters that are going on. And they make pretty intuitive sense when you think about it. We also learned that we can change that filter context with CALCULATE, that's what it does. CALCULATE's one job is to manipulate the filter context.
Something else is that the filter context propagates filters to other tables. So what does that means?. Well when we have a relationship between Product and Sales Order Detail table. And whenever we would filter on product color, whether we are doing it implicitly or explicitly, that filter would propagate down to the Sales Order Detail information. And so the Sales Order line items would get filtered as well, that's called cross filtering. When you have a filter context, it travels across those relationships. And we're going to see that's not the case when we deal with row context.
Row Context
Row Context limits to current row, and occurs when you're iteration through rows.
One case is it's used in calculated columns, and so whenever your're using an expression in a calculated column, it's able to refer to multiple columns because it's limited to just that row, so it knows exactly what you're talking about, there's nothing you need to aggregate, there's nothing fancy you need to do.
Row Context also occurs in iterators. These are the two main places you're going to see this, in a calculated column or an iterator, and so when the iterator is going row by row, for each row it creates a row context. It says you're limited to just this set of information. Additionally it doesn't propagate filters. So if we were to be using an iterator on the Product Table and maybe going through each product, that would not automatically filter anything on Sales Detail Table, and in fact we wouldn't even be able to access the Sales Detail Table normally. What we've to use is either the RELATED function or RELATEDTABLE function. So you're going to notice that the only time that you have to use RELATED or RELATEDTABLE is when you're in a row context, that's why we had to use it in calculated columns, but whenever we were dealing with measures, we didn't have to worry about any of that.
So those are the difference between filter context and row context. These are the two things, the only two things that affect what happens whenever you evaluate an expression. A filter context is just all the filters that have been applied or manipulated, and a row context is the row specified by a calculated column or an iterator behind the scenes.
Filter Context | Row Context |
Combination of visual filters and user filters | Limits to the current row, when iterating |
Can be changed with CALCULATE | Used in calculated columns |
Propagates filters to other tables | used in iterators |
Does not propagate filters | |
Requires RELATED/RELATEDTABLE to use other tables |
Nesting Evaluation Contexts
Finishing up with the idea of evaluation context, let's go into something really advanced and talk about nesting. We can nest evaluation context. Specifically nesting row context.
= RANKX( // Creates a row context
All( Products ), // Over all products
SUMX( // Creates a new row context for each product
RELATEDTABLE( InternetSales ), // Pulls sales based on the inner row context
'InternetSales[SalesAmount]'
)
)
Now this code is from an example from Microsoft, and is based off one of their Adventure Works databases. So the first thing we have here is the RANKX
function. You can tell by the name, the X at the end, and the parameters that is takes in, that it's an iterator, because it's taking in a table and an expression, and because it's an iterator it's going to create a row context and loop over what table we passed into it.
In this case we're going to pass in all of the products, so we're going to undo any filters and we're going to return a table. ALL
returns a table and we're going to return the Products Table. The reason we're doing this is we want an absolute ranking. So we want to rank all of the products, no matter what's been filtered. So we have to rank based on something, are we going to rank based on alphabetical order of the description of the product? No that would be silly. Are we going to rank on quantity sold? Aw, that's a little bit closed, but what we care about is the total sales. So we're going to use SalesAmount. And to get that, we need to use another iterator because the information we care about is in a different table.
So we're going to use SUMX
and so SUMX
is creating a new row context because first we're going through each product and then for each product we're going to go through each row in the InternetSales Table. So we're going to pull in sales based on that inner row context. So this is where it gets interesting. Let's take a step back. We have a product table and we're going to loop through each product one by one, Product A, Product B, Product C. And let's say we're on Product A, well we're using the RELATEDTABLE
function on the sales table, this returns all of the sales for the current product, product A, and then SUMX
loops over each of the sales entries. If your head is spinning, don't worry. It's rare that you're going to have to nest iterators, but the important part is that you understand that you can and that evaluation context can get a little bit complicated.