MSPTDA 19: CALCULATE DAX Function & Filter Context & ALLSELECTED & KEEPFILTERS (50 Examples)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Welcome to MSPTDA video number 19. Hey. In this video we got to talk about the most epic function in DAX, the CALCULATE function. And we have to talk about filter context. These two work together. Yes, we have filter context from the external report. Those are the conditions or criteria that help filter our underlying data model to get our conditional calculation. But the CALCULATE function is the DAX function that allows us to change the filter context. Also in this video, we'll talk about ALLSELECTED and KEEPFILTERS, two mysterious functions that interact with the filter context. And of course, since we're talking about DAX and data modeling, all the topics we cover work in Power BI Desktop or Excel PowerPivot. Now, here are some of the topics we're going to cover in this video. And if you want to follow along, there's a number of different files that we're going to use. This is the file we're going to start off with. Now, over on the DM for data model one table, we're going to start off with a very simple set of tables. There's our fact table, fTransactions with an s, and the dProduct table. I've already imported these into the data model, so PowerPivot data model. In our PowerPivot window, there's diagram view. We can see we have a simple fact table and a many to one relationship with our product table. We've already calculated total sales. If I go over to data view, fTransaction table, total sales is a simple sum function. But let's start off with the basics of what is filter context. Alt Tab, jump back over to Excel. I'm going to click in a cell, go up to Insert Pivot Table, or the keyboard, Alt, N, V. It knows we have a data model, so it's automatically selected. I click OK. Open up fTransactions and dProduct. We're going to drag product from the dProduct dimension table down to rows. Total sales, f of x means that's a measure down to values. Now, what is happening here? That is a condition or criteria from the external pivot table over in Power BI Desktop. It could be any one of the visualizations. But we almost always have conditions or criteria externally that are going to flow in and influence the measure. Over here we can manually see that these three rows were used in the adding process to get 35. But internally, underneath, the Quad criteria condition from the external filter context flows into the measure and helps filter the table. Now, visualizing this, we go from the full product table, it gets filtered down to just a single row showing Quad. Because there's a one to many relationship with an arrow, that arrow indicates the direction of the filter and how it flows. That Quad filter flows across to the fTransaction table, filters the table down to just the rows we want. So that means the Sales column has only the numbers for that particular condition or criteria. Then once the table is filtered, then the measure makes the calculation. Now, if you think about Excel and you know array formulas, when you make conditional calculations, it has to iterate over every single row, even if the rows don't meet the condition. So one of the beautiful things about the data model and DAX formulas is this filtering ability to make whatever column we're making a calculation on smaller. Then the formula makes the calculation. Now, so far what we've talked about in this video we've already talked about in earlier videos. But in a video about CALCULATE, we want to make sure we have all of the basics down before we get to the much more complicated CALCULATE DAX function topics. Now, we have external filter context. Now we need to talk about the CALCULATE function, how it changes the filter contexts, and the filter contexts inside the CALCULATE function. We can go over to our data model. Below total sales, we're going to create a measure. I'm going to click up in the formula bar, colon, equal sign. And the letter C will always get me to the CALCULATE function. So I can simply type C and Tab, expression. Now guess what? We're using CALCULATE, and it expects a scalar expression, that means some measure that calculates a single answer. We could equally use CALCULATETABLE. And in fact, most of what we do in this video will be all about the CALCULATE function. But everything we learn about CALCULATE is equally applicable to CALCULATETABLE. CALCULATETABLE expects a table, and then we change the filter context for the table. CALCULATE takes an expression, some measure, and changes the filter context. Square bracket, and our convention is always to put our measure name in square brackets only, comma, and the filter. Now we can do multiple filters and then CALCULATETABLE and CALCULATE. All of these filters will work internally as an AND logical test. Now, I'm going to backspace. We simply want to go to the dProduct table, down arrow to the Product column. Then I'm going to type a Boolean logical test. Hey, everything in that column, are you equal to, in double quotes-- this is text-- the Quad product? Close parentheses. Now, a Boolean filter means we have some column. There's a comparative operator and then some value that we're going to check for in that column. And we'll talk a lot about Boolean filters through the first couple of examples. But right now all we want to see is we have a new filter internally inside our formula. Another important thing about calculating CALCULATETABLE as opposed to the FILTER function, which we saw last video, in the CALCULATE function we can use any column from any table in the entire data model. That's different than FILTER, last video, where we had to use a column from the table in the first argument of the FILTER function. All right. We have our internal filter. I'm going to hit Enter. Now, over here in the measure grid, there is no filter context. Or wait a second. There's no external filter context. But inside the formula, there's internal filter context giving us the total of $35 for the Quad product. Let's go drop this in the pivot table, Alt Tab. Over here I see my new measure, Quad total sale. So I drag it down. And look at that. I get $35 everywhere. Now, where would you use something like this? Well, maybe you're comparing each one of the other revenue amounts for the product against the Quad product. But for us, it's going to help us illustrate internal and external filter context. Now, as a basic lesson of how this measure is calculated, before it ever filters the underlying tables, it has to decide, since there's the Product column inside the measure and the Product column is in the row area of the pivot table, it has to decide which column to use. Do I use the internal column and the condition Quad, or do I use the external column and the condition Carlota for this row or Quad for this row? The way it works is this. When it's given internal and external filter context and the column exists in both places, the internal column and its filter will replace the external. Now, technically what happens is, since there's external and internal, for a moment the column exists in both places. But once the engine realized that it's in both places, it removes the external and keeps the internal. Then it will run an AND logical test. Now, here it doesn't really make sense because once it removes it out here, there is nothing out here. But later we'll see that when it removes a column from the external, there might be external other filters. So the column exists in both places. External one is removed. It's run as an AND logical test, which means no filter out here, Quad here, and that happens for every single cell. And that's why we get $35 for every single row. For our next example, we're going to use this Power BI Desktop file. And what we'd like to do is use the same Boolean filter in CALCULATETABLE. Here's the same fact table, relationship, and dimension table. Over in table view, I can come up to Modeling. Click on New Table. We're going to name this table Quad Transaction, equal sign, C. And there's CALCULATETABLE. Notice, because I'm in the context of creating a new table, when I type the letter C, CALCULATETABLE comes up. Tab. The table we're going to filter is fTransaction, Tab. And there it is. We can use our filter. Comma, dp, down arrow to product. Hey, are any of you equal to, in double quotes-- this is a text, literal in double quotes-- close parentheses. And now when I hit Enter, calculate table has taken the full fTransactions and filtered it. Now, when we create a table like this, there was no external filter context on the fTransactions, so we used our internal filter. It created the filter context, filtered the table, and delivered it to the data model. Now, over in Excel, we can't create a table like this and put it into the data model. But over here in Power BI Desktop, now we have a new table in our data model. So when we use CALCULATETABLE or CALCULATE, we can use just an internal filter to change the filter context. We can use an internal and external filter and merge them to change the filter context. But guess what? The calculating CALCULATETABLE function can do one other amazing thing. It can change the filter context by taking all available row contexts and converting them to an equivalent filter context. And that, of course, is called context transition. As an example, we'll go over to the data model. We're on the dProduct sheet. I want a new column to calculate from the sales table the total sales for each product. I'll call this Calculated Column Product Sales. And up in the formula bar we'll type sum, ft, down arrow to sales, close parentheses. But guess what? This is an aggregate function. There is no external filter context here. So when I hit Enter, I get the grand overall total. Now, maybe that will be useful in a particular formula, but that's not what we want here. I want that Quad condition or criteria to filter the fTransaction table in that cell. When I get down to this cell right here, I want Carlota to filter that fTransaction table. Well, the CALCULATE function comes to the rescue, because the CALCULATE, if I wrap it around the sum, will take any available row context and convert it to filter context. So before sum, type the letter C, Tab. Now, we don't have any filters here, although you could put them there. So all we're going to do is put the aggregate function and expression, close parentheses. And when I hit Enter, now $35 right there. That's because the Quad row context converted to filter context filtered the fTransaction table. Now, the CALCULATE does oh so many amazing things. If I create a second column, product sales two, and Enter, this time I'm simply going to square bracket, t. There's my measure, total sales when I hit Tab and then Enter. Oh, as we studied earlier in the class, every single measure you ever use has a hidden calculate function wrapped around it. So anytime you use a measure anywhere, you have to be aware that the formula will pull any available row context and convert it to an equivalent filter context, which, of course, is exactly what we want in this calculated column. So the CALCULATE function can use just internal filter contexts. It can merge external and internal together. It can do context transition. And all measures have a hidden calculate. Now, our next topic, we're going to go over to the fTransactions, and I'm going to click on my Boolean filter inside CALCULATE. And we need to talk more about what's exactly going on when we build a Boolean filter. Now, what's really going on with this Boolean filter is actually there's a little mini table right there that has the product field name and the one condition Quad. Now, that's not what we put there. We put column, comparative operator, and criteria. Every single time you do that, here's what's really happening behind the scenes. So I started our third measure, and I named it Quad Total Sales FILTER ALL. There's the measure. And to create that mini table, we use the FILTER function. Now, the FILTER function will deliver a table. What we need is a table to filter. And here's what the Boolean does behind the scenes. It will always use the ALL function on whatever column we used in the Boolean expression, down arrow to product, close parentheses. The reason that the DAX engine uses the ALL function to create the table is because the ALL function does not see the external filter context. Because the goal of our formula when we're doing Boolean is to show Quad in every single cell, we need to have a table that's not going to be influenced from the row conditions or criteria for product from the pivot table. So ALL is exactly the correct table function that we want to use in the first argument of the FILTER function. The ALL function will deliver a unique list of all the products from the Product column. Then it internally will repeat exactly what we typed out. Hey, that particular column, are any of you equal to the Quad? Close parentheses. So this construction right here, a lot more typing to do, but that's exactly what happens internally in the DAX engine anytime you create a Boolean filter. Now, I'm going to close parentheses and Enter. We could see it gives us 35 here. I'm going to add some number formatting. We're going to go drop it into a pivot table, but then we're going to go over to DAX studio, because I want to show you exactly what's happening with that formula. Alt Tab. And now over in our pivot table field list, there's the filter ALL. Drag and drop. So it will do exactly the same thing as our Boolean filter that we typed out, but internally it's using FILTER and ALL. Now, luckily we don't have to type out FILTER and ALL every time. We can do just a Boolean expression. Now, let's go over to DAX Studio. I've already downloaded this. We've used this a number of times earlier in the class. I'm going to click DAX Studio. Because we opened it from within Excel, it sees our data model. I'm going to connect. Over here on the left I'm going to open up dProduct and fTransactions. Over here on the white, I'm going to Control and roll. This is where we can create our DAX query to evaluate table functions and have a preview of them below. We use the EVALUATE command. And we're going to start with ALL on the Product column, close parentheses. Up here, Clear Cache and then Run. I'm going to run this. So we can see the ALL will always give us a unique list. And notice there's a field name at the top and then the unique list. Now we're going to use this inside filter. So there's the table in the first argument of filter, comma, Enter. Double click Product over here. Are you equal to, in double quote, Enter, backspace, and close parentheses. Now, as the formula element that is internally created when we type out a Boolean, it does what it's supposed to do. It takes this condition, and there's the table in the first argument of FILTER. It iterates over each column, gets a true or false. There's only a true for Quad, so this whole thing, when I click Run, evaluates to just what we need inside the calculate function filter argument, a little mini table, a valid list of values that we use to figure out which records to include. This is the internal filter context. Now, there's another important insight we can gain from understanding, when we type a Boolean, then internally the DAX engine uses FILTER and ALL. If we go back over to Excel, remember, the goal of this formula, Boolean, or internally, the FILTER and ALL, is to calculate the same number in each cell. That will always happen when we do a Boolean. How does that happen? Well, guess what? From our study last video about table functions, we know that the ALL function doesn't see the external filter context. So for every single cell on the pivot table or the Power BI visual, this ALL function will always deliver a complete unique list of products. That's different than the VALUES function. If internally it used the VALUES function, we would not get the same value in every single cell. Now, I actually want to go try that and compare and contrast the code for a Boolean and if we use the same construction but with values. Let's go back over to our data model. I'm going to copy this FILTER and ALL formula, Control C, Escape, come down one cell blow, up to the formula bar, Control V. And instead of FILTER ALL, I want to type values. And then instead of in the first argument of FILTER, I want to type VALUES. Now, this is not what is generated internally when we do a Boolean value. If we want the result of this formula, we're going to have to type this one out. So what's happening here? We have our FILTER function, which is going to deliver a valid list of values to the CALCULATE function to calculate total sales. But the difference is VALUES. We'll see the external filter context. VALUES will always be a single row table for each row in the pivot table. The filter context will flow in. Let's see in the pivot table how this works. Of course it's going to run an AND logical test now, because the FILTER function right here was iterating over a single table that had Carlota. It asked, is Carlota equal to Quad? False. It got an empty filter, so nothing. Here, the values function was looking at a single table. That means this condition or criteria flowed into values, values had a single Quad table, and then the condition was asked, hey, are you Quad? True. So if we want Quad total sales in every cell, we just type out a straight Boolean. If we want something different, then we're going to have to build our own table function to deliver the correct valid list of values to calculate. The next topic we want to cover is, what if we have a Boolean filter but we do not want to hard code the value into the formula? We want to pull that condition or criteria from a table in the data model. No problem. We can do that with the VALUES function. Over here in Excel, we have a fact and dimension table. But if you scroll down, we have two other tables that will help us illustrate all the different awesome things with CALCULATE. Here's a variable table. That's the condition or criteria I want to pull from. Now, I've already imported this into the data model. Over here in diagram view, there's a single column and single row table with our variable. Data view. And I want to use the same formula, Control C, Escape, down below. Up to the formula bar, Quad Sales, criteria from VALUES. And we want to, instead of having hardcoded value, we're going to use the VALUES. Now, dis means disconnect the table because there's no relationship between this table. There it is, the Variable column. Close parentheses. Now, the amazing thing about VALUES, and we've talked about this last video, it can deliver a unique list of values in the current filter context. But if it's a single value, it will convert it to a scalar value which can be used in the formula, which is exactly what we need for our condition or criteria in a Boolean calculation. Also, since this is disconnected, there is no external filter context, so VALUES on this column will always give us just that one single input value. When we hit Enter, we get our 35. We can add some number formatting. Back over in our pivot table, we can click and drag. Right now we're getting 35. But if we change this to Carlota and refresh our pivot table, now we get 45. Hey, that's not a good name. Back over here on the data model, I'm just going to change this to Total Sales Criteria from VALUES, and ENTER. And there we go. It has updated. Now, we need to talk about AND and OR logical tests when we're doing a Boolean filter inside the Calculate function. Back over here in the measure grid, we want to create a measure that calculates the sales between $10 and $20. And we're going to do it using a single filter argument. Now, we're going to ask the question of the fTransaction Sales column, how many sales in this column are greater than or equal to 10? And because we're going to construct it in a single argument, we're going to learn a very different AND logical test operator over here in DAX. Ampersand, ampersand. One after the other means we're doing an AND logical test. FTransactions of the sales, the upper limit will be less than 25. Close parentheses. Now we can hit Enter. There's 75. That's the answer. Add some number formatting. How did this filter work? Well, here's our fTransaction table before filtering. Here's our two conditions. It ran that condition across the table, getting trues for all the rows. Then it took the total and added to get 75. Now, doing a double ampersand to run an AND logical test in a single filter argument, that's not the only way we can run an AND logical test. If we come down to this next measure right here, well, of course, since CALCULATE gives us multiple arguments, and they together will run an AND logical test, this is another way we can construct a Boolean AND logical test. Still another way, the AND function. The AND function will allow us to do it in a single argument without using that double ampersand. Now, we've got to talk about a very important rule or restriction for Boolean filters inside the CALCULATE function. We used double ampersand. In just a moment, we'll also see the double vertical bar or pipe for the OR logical test. But when you do this, you cannot use two different columns in the same single argument Boolean logical test. Now, there's easy ways to get around this. But we have to remember that. And, in fact, if we try it, which we will later, we'll get an error that reminds us, you can't use two different columns in a Boolean test in a single argument. Now, the reason that you're not allowed to do this is because of the DAX engine. The DAX engine has a hard time taking two columns and converting them into that ALL function in the first argument of FILTER. And if they have to replace columns in the external filter context, they don't know what to do when they have two columns. Nevertheless, I'm going to hit Enter here. And now we'll see the simple solution when we have an AND logical test. With this measure, I want to calculate the Carlota sales when the transaction amount was greater than 15. So dProduct, we'll do the product. Hey, are you equal to Carlota? And just for a moment I'll make our error. Double ampersand, fTransactions sales, are you greater than 15? When I hit Enter, it's polite. This expression contains multiple columns, but only a single column can be used in a true/false expression that uses a table filter expression. Well, in this case, we can simply backspace, comma, and very carefully come to the end, and Enter. And there's our total. Now, if we look over here in our fact table, we can see, here's all the Carlota records. Did the filtering work to get the correct total of 40? Yes, it did. These two transactions are both greater than 15. When we add them, we get 40. Now, we saw four examples of AND logical tests. Now let's do an OR logical test. Now, this measure's called Freestyle Boomerang Sales. And that's because this group is made up of the Carlota boomerang or the Quad boomerang. Now, in our transactional data set, we only have two different products that we sold. But here's how we do it as an OR logical test. Hey, product, are you equal to Quad? And then, just like there's a double ampersand, we have to find the vertical bar or the pipe and put two pipes, one after the other. That in DAX means an OR logical test. Then we can check and see if the product is Quad or Carlota. Close parentheses and Enter. Now, we got away with this, of course. Single filter argument, two columns, but they're both the same column. Now, there's an alternative. I'm going to copy that and down below. And I'm going to call this one OR. And instead of using two pipes, we can use the OR function. Just like there is an AND function over here in DAX, there's an OR function also. So when I hit Enter, I get exactly the same. Now, if we had two different columns, we could not use the OR function. Because, guess what? Those two Boolean logical tests are still in a single filter argument. So unlike an AND logical test where we're allowed to use filter two, filter one, we can't do that with an OR logical test. Later in the class we'll see how to do an OR logical test on two different columns using the filter function. All right. So we saw four examples of Boolean AND and two examples of Boolean OR logical tests. Now, for our next Boolean example, I would like to, inside the filter argument of CALCULATE, compare the Price column and the Cost column from the dProduct table directly. Now, in retailing, there's something called keystone. Keystone means when the price is double the cost. So I want to ask the question inside the formula, hey, how many of the products have a price that's double or greater than the cost? For Quad, we can see that 43 is not double the cost, so we do not want to include that in our calculation. But Carlota, that price is double or greater than the cost, so I want to include this product in our calculation. So in our measure, we're going to directly compare these two columns and calculate total sales for keystone products. Now, this measure is going to be called Total Keystone Sales. There's our measure in the expression argument and our filter. DProduct, and I'm going to down arrow to price. And I'm going to say, how many of you in that column are greater than or equal to items in the Cost column? Times two. Close parentheses and enter. Well, of course I'm going to get the same error as when we tried to do this before. Two different columns in the same filter argument, it's not going to work. No problem. We can put this logical statement into the FILTER function. The only question becomes, since we're using FILTER, these two columns both have to be in whatever table we put into the first argument of FILTER. I'm going to use the ALL function, close parentheses, comma. And as we learned last video, ALL works on a single column, multiple columns, or a full table. I'm going to do dProduct, price, comma, dProduct, cost. ALL will give us all the combinations between prices and cost. The FILTER expression can now iterate over this table, get true or false, and FILTER will deliver a filtered list of valid rows from the product table that CALCULATE will use to filter the sales. If I come to the end and Enter, we get an answer of 45. If we look over at our fact table, we can see, since the Carlota is the only product that's keystone or above, when it filtered the fact table, the measure got exactly $45. Now, I'd like to go copy this formula element, Control C, Escape. We'll go back to DAX Studio, Control V. Now we can add a little formatting over here in DAX Studio, Format Query button. And when we click Run, there's the price and cost for the only one record in the product table that matches. These values will allow the product table to be filtered down to just the Carlota row. That filter flows across the relationship, filters the fact table, and total sales can calculate the total of $45. Now, for our last Boolean example, I'd like to go back to the measure that calculated sales between transactional amounts of $10 and $20. We did an AND logical test in two columns. But what I'd really like is to have, in the row area of the pivot table, the lower and upper limit. Well, if we go back over to our Excel sheet and scroll down, here's exactly the table that I've already imported into the data model. It has the lower and upper limit, and it has a category. I want to use this category in the row area of the pivot table, and then the formula needs to access for each row the lower and upper limit. Now, we're going to start off. I'm going to come over here below this pivot table, Alt N, V, data model, click OK. Dis for disconnected table. There is no relationship between the fact table and this one. Category, I drag it down here. By the way, as we saw earlier in the class, when I created this, this would not sort correctly. So in the data model, we sorted category by lower limit. Now, the goal of the formula is to use the upper and lower limit and count how many sales amount fit into each category. Sounds like exactly what we did in our prerequisite statistics class a lot. But now we're doing it with DAX formulas. So in order to create a measure, to create our frequency distribution to count between these categories, we're actually going to use a great DAX function called COUNTROWS. COUNTROWS will point to the entire fact table. Then as we iterate through in the pivot table, each one of the lower and upper limits, the table will be filtered down to just the number of rows that meet those upper and lower limits. Then the COUNTROWS will count the number of transactions. And, boom, we'll get our frequency for each row. Now, over here in the measure grid, we're going to create our first measure, COUNTROWS in Sales Table. COUNTROWS fTransactions, Tab. Close parentheses and Enter. That's six, the overall count of transactions. Over here in our pivot table, if we drag our new measure down to values, oh, no, we're going to get a count of six all the way down. There is not a relationship between this Category column, and the disconnected sales limit, and our fTransactions. But no problem. We will access-- from having this in the pivot table external filter context, we'll access the lower and upper limit to filter the fact table. Now, looking back at one of our earlier formulas, notice we use the VALUES function to get at a particular value. That's not going to work for getting the lower and upper limit. Because in the grand total cell, I'm going to have to pick out the min and the max in order to get the correct lower and upper limit. So instead of using VALUES, we're going to try to use the MIN and MAX to get our conditioned to use on the other side of a comparative operator. So down on the measure grid, we're going to name our formula Sales Frequency, the CALCULATE function, the measure we're going to have in our expression, COUNTROWS in Sales Table, comma. And now we need to change the filter context so we don't get just a count of six. FTransactions. And I'm going to say, hey, all you values, how many of you are greater than or equal to the min of the disconnected lower limit? Now, as we copy the formula down, the MIN will always pick out the correct lower limit for each one of those categories and in the grand total cell. Now I'm going to use double ampersand because we're doing an AND logical test. And now I have to say, how many of you are less than the upper limit, which is the max of the disconnected upper limit? Close parentheses. Close parentheses. Well, the problem when I hit Enter, using aggregate functions on the other side of a comparative operator, that is not allowed. That's what the error says. Luckily, the FILTER function will come to the rescue. I'm going to filter what table? Well, of course the fTransaction, comma. There's our filter expression. This filter expression in the FILTER function can do a lot more than a straight Boolean. And in this case, it'll have no problem using the MIN and the MAX on the other side of a comparative operator. Close parentheses and Enter. Now we get a six here, because there's no external filter context. But when we drag, this shows up because there's not a relationship. It's not smart enough to know that we have a disconnected table that's not supposed to have a relationship. I'm going to drag this down to the values. And just like that, we get our correct count. And we can check this. How many transactions are there between 10 and 15? Two. And there they are, between 10 and 15. Notice the lower limit is included, upper limit not. Of course, we do that intentionally, because if we're using the upper and lower limit in two different places, one of them better not have the equal sign. The other one better have the equal sign. Now, taking a closer look at this measure and how it acts in each cell on the pivot table, notice the measure there, fTransactions, all of those do not have any external filter context. It's only the MIN and the MAX functions that are influenced by this column from the external filter context. Remember, the way this table looks is there's the category. There's the lower and upper limit. So as this measure copies down for this row, for example, MIN only sees the lower limit for that one row, which would be 10. MAX sees only the one row, max of 15. It's not until this formula gets down to the last grand total cell that the MIN and MAX are picking from the whole column of lower limits and upper limits. Now, to help illustrate how this formula is calculating, I'm going to do something kind of crazy here and use an Excel spreadsheet example to show you what's going on under the hood in the columnar database in DAX engine. Because really, the hard part of learning DAX is because we can't visualize it the same way as we can in Excel. But here it is. We have CALCULATE working on COUNTROWS. COUNTROWS is counting how many rows are in the fact table. This FILTER function's job is to provide a valid list of values that can filter this table. FILTER looks at the fTransaction. That's the whole table right there. It's looking at the Sales column right there. But look at this. The comparative operators are looking at the MIN and the MAX. But these columns are coming from this table. Well, let's think about this row in the pivot table right there. The measure gets filtered because that condition or criteria from the row area flows into the measure. That means this table is filtered down to just a single row. That single row is what is seen by the MIN and the MAX in this row. Then the two columns are compared to the lower and upper limit. Once we get a series of trues and falses for the fact table, then the FILTER function actually filters the table. This is what it would look like if we did it in Excel, greater than or equal to 10, less than 15. And now we have our filtered table. That's what FILTER delivers to the FILTER argument inside the CALCULATE function. Then once CALCULATE sees this filtered table, COUNTROWS, the measure, it can do its job and count and get a count of two rows. Another important aspect, if I completely unfilter both of these, that's what's happening down here in the grand total cell. That's why when FILTER is looking at the MIN and the MAX down in the grand total cell, MIN is looking at this entire column picking out zero. MAX, it's looking through this whole column and picking out 25. Of course, for the FILTER function, all the columns are between zero and 25, so FILTER delivers the entire table. CALCULATE counts all the rows in the table. Now, on our next example of how to use CALCULATE, I want to, in this pivot table I just created here, compare each one of the individual items to the grand total. Well, of course, if we're using a data model pivot table, we then need, in each cell, to have the grand total. We actually have already seen this formula earlier in the class. We want to calculate grand overall total, CALCULATE. There's our total sales, and we need to change the filter context. And how do we want to change the filter context? Well, we want to remove every single filter that might be applied in the external filter context. Well, the function we use is the ALL function. Now, we've used the ALL function last video a lot and in this video a lot. But in this video, we were using it in the first argument of the FILTER function. Anytime you put the ALL function inside the Filter One argument, in CALCULATE, it becomes the remove operator. So if our goal is to remove every single filter possible, then in a star schema data model, we use the fact table. Because all the dimension tables feed into this if I use ALL to remove every single filter on every single column, It'll remove all the filters in the data model. Close parentheses. Now, remember, ALL, we could put a single column here, we could put multiple columns, or we can put a table, in our case, the fact table. Now, when we use this as a filter, every single cell will just see the entire fTransaction Sales column. Close parentheses and enter. Over here in the pivot table, now we can drag our grand overall total down to the values area. And there it is, the same grand overall total in every cell. Now, as the numerator, we need to take for each row in the pivot table our total sales, and then the denominator we'll use our grand overall total. The measure name will be percent of grand overall total. And we'll use the DIVIDE function in the numerator, square bracket. And we want total sales, comma. In the denominator, square bracket, and we'll use grand overall total. And the third argument, if we leave it empty, if our formula gets a divide by zero error, then it will show a blank. Close parentheses and Enter. We want to add some number formatting. Over in our pivot table, we drag percent of grand total. And just like that, for each row in our pivot table, the numerator gets the correct total sales. The denominator gets 80. Now, before we jump over to a different Power BI file with a larger data set and look at some advanced topics, let's review what we did here. We saw how to do a Boolean filter inside of CALCULATE to change the filter context. We saw that a Boolean always gets converted to filter in ALL. If instead of ALL we used VALUES, remember, ALL doesn't see the external filter context whereas VALUES does. We saw how to use VALUES to get a variable on the other side of a comparative operator. We talked a lot about AND, and an AND logical test can be done with double ampersand. It can be done in the two different filter arguments. Or if it's the same column, in one filter argument you can use the AND function. We saw how to do two different columns with a filter. Remember, the CALCULATE can see the whole data model, so we can put whichever columns from the data model we want to filter that fact table. We saw how to do an OR logical test with a double pipe. We saw how to use the OR function. We talked about comparing two columns directly. No problem. We couldn't do it with Boolean, but we could do it with the filter function. We saw how to COUNTROWS with the COUNTROW function. We wanted to use MIN and MAX on the other side of a comparative operator. We couldn't do it as a Boolean, but FILTER let us do it. And then we saw how to use the ALL function as the remove operator in calculate. All right. Now let's jump over to a different file. Now, over here in this Power BI Desktop file, which you can download, here is a picture of the data model. We have fSales. And there's four dimension tables-- sales rep, customer, products, and date. If we go over to data or table view, here's our fact table date. And there's three foreign keys-- sales rep, product ID, and customer. The only fact we have in the fact table are the number of units sold. If we go look at product table, there's the primary key, product name, and we have retail price and cost, the customer's table, the sales rep table, and the date table. If we go over to the sales table, we can see some of our measures, total revenue sum x over f sales related to look up the Retail Price times the Units column. Grand overall total, well, we did calculate it in ALL. We already calculated percent of grand total. There it is. We have a Boolean total quarter revenue measure right there. And we also have average daily revenue. If we go over to Report, we want to go down to the Overwrite tab. We already created a product report with total revenue, Quad revenue, and grand overall total. We have two slicers and West is selected. Now, we want to select a very specific cell, Quad revenue for Majestic Beaut and West. And we want to talk about what's happening inside the CALCULATE function. Because inside the CALCULATE we have Quad. Outside we have Majestic Beaut on the same column as Quad, and we have the Region column with West selected. We want to talk about what happens inside when the CALCULATE merges the internal and external filters using the overwrite operator. Here we have the result from our measure. Here's the actual measure. Notice, Quad filter on the Product column, that's the internal filter. It's listed in step one right here. In our matrix, we have Majestic Beaut from the Product column in the row area, and we have west from the region slicer. Those are the external filter contexts listed in step one here. Step two, because there's a filter on the Product column internally and externally, the external filter is removed. The external and internal filter contexts become just West on the external, just Quad on the internal. And in the final overwrite operation, the external and internal filter contexts get run as an AND logical test. Then the fact table is finally filtered down to the correct numbers and the measure can make its calculation. Now, our next topic has to do with this measure, the grand overall total. And it has to do with the ALL function. Now, if our goal is to remove every single filter no matter what's happening in the external filter context from the fact table, that's exactly what we want to do. That measure is perfect for calculating the grand overall total. But if we select our matrix and come over to our fSales table, there's percent of grand total. If I click on it, I could see total revenue divided by grand overall total. So I'm going to click and drag down to our values area. And look at that. I thought it would show me percentages that add up to 100%. Well, if I come up to region and use my eraser, well, now it's working fine. And here's the problem. That measure is always programmed to take total revenue. And since total revenue doesn't have the ALL, it always figures out what the total is based on whatever filters we have. But the grand overall total, that's always going to give me the grand overall total with all filters removed. So if I come up and select West, well, maybe this is what I want. If my goal is to take whatever total revenue is for each row and the filtered total and compare it to the grand overall total, then that measure is perfect. But if I want, in the denominator, in my percentage formula to have the filtered grand overall total, then instead of using ALL, I need to use the DAX function ALLSELECTED. Now, before we talk about how ALLSELECTED does its magic, we already have this measure down in our matrix. I'm going to type ALLSELECTED and we're going to use no arguments. Close parentheses. And watch what happens to this column when I hit Enter. There it is. There's the filtered grand total. If I change it to East, now in the filtered grand total cell for total revenue, it's the same as our denominator over here in our percentage formula. The percentages add up to 100%. Now I want to change this back because we do want to keep the grand overall total. We want to keep our percentage of grand total so we can compare filtered amounts to the grand overall total. Now we'll create a new measure with the ALLSELECTED. But first, before we do that, we have to talk about how ALLSELECTED got to this filter context in that grand total cell. The answer comes from how a measure calculates in a visualization over here in Power BI Desktop or in a cell in a pivot table. Notice that row condition or criteria flowed into the measure. And the way it flowed into the measure is through context transition. Just like a formula iterates down a calculated column or through an iterator, a measure in a pivot table sees that filter context, which is row context, and its context transition which pulls it in. Here, context transition pulls the Quad in and converts it to an equivalent filter context. So what ALLSELECTED does when it gets to this cell is it rips away that one row condition or criteria and jumps back before this row context to the full filter context available in this cell. As a visualization to understand what ALLSELECTED does, if we had row context on the Quad product and ALLSELECTED removed it, it would jump back to the complete column of product names. As another example, this is the same example we just did in Power BI Desktop, but this is in Excel, if the measure is looking at the row context Quad and context transition brings that Quad into the measure, ALLSELECTED will remove the last filter created from context transition and jump back to the previous filter, which, for this example, would be Carlota, Quad, and Sunshine from the Product column and West from the Region column. ALLSELECTED removes that row condition, and instantly it will see all of the products, Carlota, Majestic Beaut, Quad, and Sunshine and the region West. the full filter context in that total revenue filtered grand total cell. Now, the reason we need to think of this process as context transition is because, if you try to use ALLSELECTED to get back to the grand total cell filter context and you have ALLSELECTED in an iterator, it will not be able to jump back to the context outside of this row. Here's an example of using ALLSELECTED where it can not get back to the visualization or pivot table grand total cell. This ALLSELECTED can only jump back to the dDate table where, in the dDate table, there is row context. So ALLSELECTED would remove the individual day from row context, but then it would see the entire dDate column. So a formula like this will not accomplish the goal of getting back to the filtered grand total cell. And the reason is because ALLSELECTED bumped into the dDate iterating row by row in the average x iterator. It removed the last filter from context transition. That's why the true definition of ALLSELECTED is ALLSELECTED will remove the last filter created from context transition. But right now we want to create two measures, one for filtered grand total and then percent of filtered grand total. So over with f cell selected, model a new measure, I'm going to call this Filtered Grand Total CALCULATE, square bracket, and we want total revenue, comma ALLSELECTED. Now, you can ignore this description created by Microsoft because it doesn't portray what ALLSELECTED really does. ALLSELECTED removes the last filter generated from context transition and jumps back to the previous filter. Now, I'm going to close parentheses, close parentheses, and Enter. We have our new filtered grand total. We're going to drag it down to our matrix. And sure enough, when I change this to East, wow, look at that. It's cut the filtered grand total. Now, selecting fSales, New Measure, our measure name will be Percent of Filtered Grand Total, equal sign, and we want to divide with total revenue in the numerator, comma, and our filtered grand total in the denominator. Close parentheses and Enter. We want some percentage number format. There's our new measure. I can drag it down to our matrix. And that's beautiful. Now, look at this. We might want this measure, Percent of Grand Overall Total, sitting right next to this one. Whatever I use as a filter, now I get the correct filtered grand total sitting in the denominator for this percentage. And this one, it's still got the grand overall total. Now, to illustrate another great feature of ALLSELECTED, we have a cross-tabulated report, sales rep, and product. And I have filtered down to the customer, Twitter. There's the filtered grand total. If I remove total revenue and add the filtered grand total, is it going to work for both the row and column headers? You bet. I can come over here and filter to Amazon. ALLSELECTED removed whatever the column and row headers were and got back to the filter in the grand total cell. So yes, it will work on a cross-tab. Over on AS2, here's this ridiculous formula where we used ALLSELECTED. And that ALLSELECTED is never going to make it back to that filtered grand total cell because it bumps into the dDate table. Over here, average daily revenue, that measure correctly iterated over all the days in January, got the total revenue, and calculated the average. But right here, although the January dates did flow into dDate-- so the iterating table only has days for January. But forget it. ALLSELECTED removed the row context. So when this total revenue iterates over all of the 31 days, each cell gets the grand total for January, which we can see right here as total revenue. Each cell has that grand total for January. And then, of course, average just averages the same number. So that's how we get that ridiculous number there. So when we're looking at ALLSELECTED, we're looking backwards. If that CALCULATE's not sitting and iterating in the pivot table, then it's not going to make it back to the pivot table. Here it's iterating and only making it back to dDate. Over here, our filtered grand total formula, we know that CALCULATE's iterating through whatever the report is. So ALLSELECTED will remove the last filter from context transition and get back to that filtered grand total cell. All right. Our next topic is going to be the KEEPFILTERS function. Now, for this example, we're going to use this file right here. On the table sheet, we have a similar data set to the data set we used in our last Power BI Desktop file, except for this fact table has about 50,000 rows as compared to 3,000 in the Power BI file. Over in PowerPivot data model, we have our tables imported. We've already created a number of measures, Total Revenue. There's sum x, average daily revenue. Only Quad Revenue with VALUES. We did this formula earlier in the video. it gives us the Quad revenue only in the row where the Quad product exists. We have just Quad revenue. That's a Boolean. We have average yearly revenue where we're iterating over the years, and average monthly revenue where we do a CROSSJOIN between year and month. All of these measures will help us illustrate the amazing KEEPFILTERS function. In diagram view, we have our fact table surrounded by our dimension tables. Over here in the Excel sheet, we want to go to KF for KEEPFILTERS. We have a pivot table product. There's total revenue and just Quad revenue. Now, remember what just Quad revenue does with a Boolean. Because this is an internal filter, the overwrite process replaces the Product column. If we wanted to show the Quad revenue only in the row where there was a Quad, well, we did this formula earlier, FILTER. And instead of ALL function, we used the VALUES function. VALUES lets all of these conditions flow in, so, of course, it simulates an AND logical test. And the only row that gets the revenue is Quad external and Quad internal. Well, there's an easier way to accomplish this than creating this formula. We can use the KEEPFILTERS function. And all the KEEPFILTERS function does is it instructs the CALCULATE function to run an AND logical test rather than the overwrite operator. That means KEEPFILTERS for every filter inside the KEEPFILTERS function, it's going to take this internal filter context and run it as an AND logical test with the entire external filter context. And KEEPFILTERS is not a table function. Its only job is to tell calculate, hey, I don't want you to do overwrite. I want you to do an AND logical test. So over here in the measure grid, we're going to create the measure called Just Quad Revenue KEEPFILTERS, comma. And we're going to use our Product column, ask if it's equal to Quad. Now, if I hit Enter right here, this is the measure grid, so there's no external filter context. It'll give us exactly the same thing. But as soon as I wrap KEEPFILTERS around that Quad product, now it's going to run an AND logical test with whatever's inside of KEEPFILTERS and the entire external filter context. So when I hit Enter, I get the same thing here because there is no external filter context. But over here in our pivot table field list, I can drag the measure down. And that is beautiful. So if we want to run a particular filter and run it as an AND logical test with everything in the external filter context, that's the way to go. If we take a closer look at how the measure calculates in the first row, the internal filter asks the question, are you Quad? The external filter asks the question, are you Carlota? And, of course, the product can't be simultaneously Quad and Carlota, so we get a false. That means the final filter context is a completely empty filter. Down here in the row for the Quad product, we, of course, get internal filter of Quad, external filter of Quad, which, in an and logical test, is true, so we get the total revenue for Quad. Now, the real reason that KEEPFILTERS as a DAX function was invented was to deal with a much more devious problem that pops up sometimes during the overwrite operation. And it has to do with something called a complex filter. Now, what is a complex filter? Over here in this pivot table, I've dragged total revenue and a date hierarchy. And here's a complex filter. We're going to come to the filter dropdown, uncheck everything. And for 2017, I want the months November and December. And for the year 2018, I want January and February. There's our complex filter. If I click OK, what I've done is I've used the Year column and the Month column, and there's an AND logical test between these two columns. Not only that, but the complete logical construction is that there's also an OR logical test. What we're asking with this complex filter is that we want the sales numbers for the year 2017 and November, or the year 2017 and December, or 2018, January, or 2018, February. The problem that's generated when we externally create a complex filter like this is that the DAX engine is going to see one, two different columns. And during the overwrite process, if we have the Year column inside our formula, it will actually remove and replace it with whatever Year column's coming from inside. Further, notice that we selected two different items. If we had selected just 2017 and then a bunch of months, we'd never get this problem. So from a logical construction point of view, the problem comes when we are mixing AND logical tests with OR logical tests and we've selected more than one item on both columns. It is the external user of the report that takes two separate columns and combines them in an AND logical test. This is how the DAX engine sees those two columns. It sees Year with 2017 and '18 and Month with four different months. This is what we are trying to do. Notice the Year and Month columns are working together. They're not separate columns like the DAX engine sees them. These two columns are together. And, in fact, they create a complete table where each row means an AND logical test. And when you go down a row, that implies an OR logical test. Those of us from the Excel side have lots of experience with complex filters, for example, when we use Advanced Filter or when we use D functions. So now that we know what a complex filter is, how is it going to cause problems? Well, it's not causing problems right here. Total revenue, notice this is the formula up here. The problem is going to only come when one of the two or both of the columns from the external complex filter are also inside the measure. And in particular, in iterator functions like average x, notice there's the Year column. So in the overwrite process, when VALUES is looking at just 2017, well, 2017 will replace the external Year column, but it will remove everything. And when it does that, it actually breaks the AND logical test. Now, to see the error in action, we're going to use this formula, average year revenue, drag it down to the values. Now, the meaning of this formula is to iterate over multiple years. And the only place that's going to happen is in the grand total cell. But the grand total cell is going to use this incorrect amount and this incorrect amount. So we have to figure out how this is calculating incorrectly. Well, this is an iterator for values of the Year column right there. That means it only has 2017. We're not iterating over anything except for a single year, 2017. But that's row context that gets converted through context transition into filter context. That means the Year column is internal in the measure. There's also a Year column in the external filter context. As soon as the engine determines year and year, this one is removed, the year inside is kept. But wait a second. What happens when it's removed? It breaks the AND logical test. And when that happens, all four months will appear in that cell right there. Now, it's not really that it appears in the cell. It's the actual measure that runs an AND logical task between the external and internal filter context to get the final filter context of all four months for 2017. Since average x is an iterator iterating over only 2017, I visualize it this way. That one row has only the months November, December, January, and February. And that's what filters the fact table, which the total revenue measure calculates as about 12.8 million. And then the average x, because there's only one row, divides by one. That gives us the incorrect answer of 12.8 million. Now, off to the side, if you wanted to prove to yourself that those four months total are actually 12.8 million, I just built a little pivot table and filtered all four months for 2017. And there it is. When four months are used for total revenue instead of the correct November and December, two months, this is called a complex filter reduction error. The same thing happens in the 2018 total row, except for this is for four months in 2018. Then in the grand total cell, it takes those two incorrectly calculated 2017 and '18 numbers and averages them to get the wrong answer. Well, how do we get the right answer? Well, we tell that Year column to please do an AND logical test with the external filter context. We're going to do our same formula but we're going to call it Average Year Revenue, KF for KEEPFILTERS. And we need our values on dDate of year, close parentheses. But that's what we want to force into an AND logical test. So we wrap KEEPFILTERS around VALUES, comma, the expression, square bracket, t for total revenue, close parentheses, and Enter. We'll add some number formatting. Now we can drag our new measure down into the values area. And look at that. That is the correct single year total or the total divided by one. And in fact, you could highlight these two cells. Look down here. There's the sum. Specifically, here's the external filter context. The internal filter context, they're run as an AND logical test. And here's the final filter context, which is only November and December for 2017. Down here, that's the correct average for these two correct values. Now, understanding when to use KEEPFILTERS means we need to understand when we can get into trouble. And to illustrate, there's no difference between this formula here or this formula right here if we do not create a complex filter in the external filter context. Notice exactly the same correct numbers all the way down. Control Z. But the thing is, when you have a report, we're using Excel PowerPivot and Power BI Desktop specifically because we want to be able to filter. However, we would like and have accurate numbers. So when you have a complex filter based on two or more columns in the external filter context and you're using the same columns inside your iterator, then you gotta worry about whether or not you need to use KEEPFILTERS. Another reason to understand clearly what KEEPFILTERS does, over here in Power BI Desktop, there's this New Quick Measure. Now, you better be good at DAX if you're going to start clicking this. Because if it creates a measure with a bunch of functions and you don't know what's going on, I wouldn't use it. But let's try and make-- I'm going to click it. Dropdown. There it is, average per category. The base value will pull total revenue and, from dDate, pull the year. We're trying to make that calculation, iterate over year, calculate total revenue, and then calculate an average. Click OK. I could see the new measure over here. And there it is, total revenue average per year. Look at that. It put KEEPFILTERS around VALUES around year, and it put CALCULATE just in case to make sure context transition happened. But why did they do that? The designers of the automatic DAX and Power BI Desktop wanted to make sure that no matter what crazy filters we might externally put on, this measure would still work. But here's the thing. It may not be necessary, just like this CALCULATE definitely is not necessary here. So when you use the New Quick Measure, well, it might get you what you want. There might be some extra stuff you don't need. CALCULATE is not needed because we have our hidden CALCULATE on our measure. And if we absolutely didn't have our Year column anywhere in the external filter, then we would not need KEEPFILTERS. But there you go. At least you know, if you're using those New Quick Measures, why they use KEEPFILTERS. Our next example is average monthly revenue. Up here is the measure. We're going to iterate using average x across, well, year and months together. We used CROSSJOIN, just like we learned last video, which will take all available years and do a Cartesian product against all months, and then calculate total revenue iterating, and then calculate the average. The problem here is there's that complex filter. And in this case, both columns are used internally in our measure. The grand total sale should be taking one, two, three, four months and averaging them to get average monthly grand total. But that's not what happens. Here is year and month. Context transition brings them in. That means there's columns internally. Well, of course they replace. And so in the grand total cell, it definitely sees the full filter context of everything. But CROSSJOIN takes two years times four months and gets eight possibilities. So down here, instead of iterating over four, its iterating over eight different months. The answer, of course, is KEEPFILTERS to force an AND logical test. Here's the measure we're using to get the incorrect answer. I'm going to copy this, Escape, click below. And up in the formula bar, we're going to change this to KEEPFILTERS. And around CROSSJOIN, we can use KEEPFILTERS, close parentheses. Now, these two columns will be run as an AND logical test with the external filter context. There it is. We're going to drag our KEEPFILTERS down here. And that's the correct 3.247 million instead of 3.23 million. Now, one other thing about this is, yes, lots of times people do do formulas like this. Then we need to use KEEPFILTERS. But if we're thinking ahead, we can avoid this whole issue by building the data model correctly in the first place. If we go over to our data model and over to the dDate table, our complex filter and the external filter context use year and month, and our formula used year and month. Well, if we want month, why don't we just build the correct attribute column that contains year and month? The fact that it's a separate column, we can use it internally in average x. And because it's a separate column, it doesn't even mess with those external columns in the overwrite process. So this is a data modeling solution that's much easier. So the other way we can solve this, copy the same formula, Control C, Escape, down here, and I'm going to call this that same one but DM for this is a data modeling solution. And I'm going to delete everything in the first table argument of average x, use VALUES, dDate. And there's my attribute column that combines year and month. Tab, close parentheses, and Enter. Now, over here, if I drag this down to values, no problem. I get the same answer, and that's that formula right there. Now, one last thing about a complex filter. I describe it as and, or, and multiple items selected on either one of the columns. Now, if you want a sure way to determine if your external filter is a complex filter, you take the original two columns, you multiply them in a Cartesian product, and if the resulting rows are the same number of rows as the original external filter, you know you do not have a complex filter. And it will not cause a problem in your formula. Running the same tests on an external complex filter and running a CROSSJOIN when you get the result, if you count more rows than the original external filter, then you know you have a complex filter. Now, there's actually a name for this type of error where we have a complex filter and we get an error. Complex filter reduction error. So if you have a chance of this type of error, KEEPFILTERS will force internal filters to be run in an AND logical test with the external filters. All right. Keep filters. Our next topic is going to be the expanded table concept. This is an expanded table diagram. This diagram represents a data model. This is a star schema data model, fact table, dimension tables with one to many relationships feeding into the fTransaction table. Now, in an expanded table diagram, it portrays what's going on here but in a different way. The table names are listed across the top. The column names are listed down the side where the yellow area represent original columns from the table. Down here, these are the original columns from the fTransaction. And the blue area represent columns from other tables that feed into this particular table through a one to many relationship. Now, this is a star schema data model. If we look at a slightly different data model, this has a snowflake where we have region feeding from one to many into dSales rep. DSales rep is feeding into one to many the fTransaction. We still read the cross-tab expanded table diagram the same way. The yellow columns represent the original columns from the table, and the blue ones are external columns from other tables that feed in through a one to many relationship. Now, we're going to be using star schema data models, so this is what our expanded table diagram will look like. And there's one, two, three uses for this expanded table diagram. The first one is we can ask, which tables will a column filter affect? So for example, if we use the ALL function on units, notice there's only one table that that filter would affect, fTransactions. But if we use the same ALL on the Product column, here's Product, we can clearly see one, two different tables will be affected. The second thing that this diagram can help us with is we can ask the question, which columns will a table filter affect? So for example, when we use the ALL function on the fTransaction table, now we have a complete list of every single column. We can clearly see that when we used ALL, it removed every single filter from every single column in the data model. In just a moment, we'll also see that we can use, without a function wrapped around it, a full table filter. And that will allow us to go backwards across a many to one relationship. So for example, if I have a particular product in the row area of a pivot table, it is going to filter the fTransactions. But if the goal of my measure is to count how many unique months we sold that product, look at this. I need the product filter to filter the fTransactions table, which, of course, it does through the one to many relationship. But then I want it to go backwards across a many to one. No problem. We can do that. If the measure is counting distinct months, I just use a full table filter. And because this expanded table has all those columns, product from the row area filters this table. And when that table is filtered down to just that product, well, of course, month is in this expanded table, so it also gets filtered down, and our measure will be able to count the distinct months for a particular product. The third thing we can do is we can see which expanded table columns are in play with any table filter. So if I use fTransaction, in fact, let's-- here's the example we'll do. We'll use not the ALL function but ALLEXCEPT. That means we can remove the filters from everything in a table except a particular column. And look at this. We're allowed, because this is the expanded table, to put the full fTransaction table and then exclude one of the expanded columns, the dDate. Now, to see a couple examples of table filters and how this diagram can help explain what's going on, let's jump over to a different Excel workbook. This is the Excel file we're going to use. Here's three tables, date, dProduct. Those are dimension tables. Here's the fTransactions. In diagram view, we can see fTransactions. And there's our two dimension tables many to one. And we already have three measures. The first one is a simple sum. Here's our first pivot table product in the row. From this table right here, we have total sales. And, of course, total sales. This product flows in, filters the fact table, and we get our total sales for that product. If we look at our expanded table diagram, here's date, product, and fTransactions. Off to the left, these are the column names. FTransaction, since this is a star schema data model, has every single column in the data model. So the way we can use the expanded diagram is this, is a complete list of all the columns that can filter the fTransactions table. So, of course, over here on the pivot table, Carlota is from the Product column. We can see the Product column drawing a line across. Well, it filters dProduct. And, of course, it's going to filter fTransactions. Now, a number of times in this class, our goal was to create a measure that calculates the grand overall total no matter what filters from the external filter context might flow in. Well, the way we do that is we use a table filter. And specifically, we put the ALL function around fTransactions. That will remove every single filter in the data model. Over here in the measured grid, we're going to create grand overall total. There's CALCULATE to change the filter context for total sales. Comma, ALL function, and here's our complete fact table, fTransactions. Close parentheses. Close parentheses. Now, we already did this formula, but now we can clearly think about this in a different way. Because we know the expanded table diagram shows fTransactions with all columns, all filters in the data model will be removed. It doesn't matter what column we drop into the row area or slice or we use. This will always give us the grand overall total. Over here in the pivot table field list, there it is. I drag it down to values, and we get the grand overall total in every single cell. Here's a date filter. If I select 1/19, of course, total sales is filtered by both a product column and date column but not grand overall total. The ALL function wrapped around that fTransactions removed all the filters. What if we use the ALL function just on the product column? It would block this filter but not this one. Now, I'm going to unfilter this. This measure will be called ALL Works on the Product Column Only. There's our expression, comma. We're going to use ALL, but this time we're going to choose a single column. So we're only removing whatever filters might be placed externally on the product column. Close parentheses, close parentheses, and Enter. Over here we can drag ALL Works on the Product Column Only, and there we go. We get 950. The ALL on the product blocks the product from the row area. If I select a date, whereas total sales is affected by both product and date, ALL Works on Product Column Only is only affected by the date column. OK. So we saw, using the ALL function, a table filter and a column filter. Now we want to talk about using a full table filter but not inside any function. And our goal is going to be this. For every product, I want to count the unique number of months that we sold that product. So for example, Carlota, if we did this manually, I can see we only sold it in one month. And for Quad, well, we sold it in two distinct or unique months. Well, the month column is in the dDate table, so we're going to have a measure. And there is an awesome DAX function called DISTINCTCOUNT. We'll use it on this column. But the problem is that is on the date table. Our filter's coming from product and going to fTransaction. So how do we get the filter to go backwards? Table filter. Over in the data model, I've already created this measure, distinct months. And there it is, DISTINCTCOUNT. We just point it to the month column. Over here in the pivot table, I'm going to drag distinct months down for each product. The problem is it's counting the entire column. And since there's only two months, we get two months everywhere. All we have to do is take that distinct month's measure, put it inside of CALCULATE, which will change the filter context, and use our table filter. There's our new measure, Count Distinct Months Product was Sold, square bracket. There's our distinct month's measure, Tab, comma, ft, Tab, the full table. Notice there's no ALL around it, so any conditions or criteria that flow in from the external filter context will filter that table. Close parentheses and Enter. Now, over here we can drag our new measure down to the values. And this is amazing. Now, actually, I've been adding some wrap text, so I'm to do that here. Home, wrap text. And there it is. We can tell one unique month we sold Carlota, two months we sold Quad. Now, taking a closer look at this measure in the Quad row of this pivot table, before we drop the measure in the pivot table, looking at the underlying data model, no columns are filtered anywhere. That Quad filter flows into the measure. If we're looking in diagram view, that Quad product filter flows across the one to many relationship over to the fTransaction table. If we're looking at the expanded table diagram, the product column definitely is in that table. So when we use that condition or criteria, it filters the fact table. Looking at the actual underlying data model, the Quad filter flows across the relationship and filters the fTransaction table. But as soon as it tries to flow this direction, it bumps into the many side. So to get it to flow across, we're going to use a table filter. Once we bring our table filter to our measure, then the full expanded table fTransaction is in play, because product and month are both in that expanded table. When the product filter flows the transaction table and actually filters that table, it flows backwards to the Month column in the date table, which is now filtered just for that Quad product. So the product table is filtered to Quad. It naturally flows from the one to many side, filters the fact table. Now that we have our table filter, Quad will flow across one to many and filter the dDate table. Then DISTINCTCOUNT can do its job on the Month column. So the question, how many unique months did we sell Quad, the answer is two, all because we have a table filter. Now, for our last example of the expanded table diagram and table filters, if it's true that fTransaction really has all these columns, we should be able to go over to DAX Studio and visualize and see this table. I don't know how to do that. But when we use the fTransaction table in any DAX formula, all these columns are really there. And in fact, you can access these columns. So for example, if we use the ALLEXCEPT, I'll put the fTransaction and ALLEXCEPT will not remove all the filters from fTransactions. It'll remove all of them except for any ones you list in its arguments. And you're not going to believe this. We can list a column from a different table that is in the expanded table. To illustrate the use of expanded columns, we have two measures already over here in the measure grid, DISTINCTCOUNT on the month-- we've already used that-- and I created Remove Everything with ALL. We're pointing to that distinct month's measure, and I'm removing everything using ALL on the fTransaction. Here's our pivot table. I'm going to drag distinct months and remove everything with ALL. Now, it's a silly formula, but we can clearly see distinct months is counting February and January 1. And then with ALL, it removes this because we use the fTransaction table month, so it sees the whole column and it gets a count of two everywhere. But you're not going to believe this. We can actually remove everything in the data model except for a month. And how do we remove everything in the data model? Well, one easy and fast way is to use the fact table. And if we remember that a fact table has an expanded table equivalent with all the columns, we can just use ALLEXCEPT and exclude the Month column. So over here in the measure grid, I'm actually going to copy this, Escape, formula bar, Control V. We don't want to remove everything with ALL. We want to remove everything except for the month. So instead of ALL, ALLEXCEPT. And ALLEXCEPT has first argument, table name, comma. And this is so crazy. We can use a column not from the original but, down arrow, from one of the dimension tables. Because dDate month is listed in the expanded table, when I hit Enter, ALLEXCEPT just did its job. It removed everything in the data model except for the month. That means this measure should be working again. Back over to Excel. Here's our measure. Drag it down. And look at that. We did just what we want, remove everything except for the month. So the expanded table diagram can help us in three ways. First, it can help us figure out which one of the tables will be affected by a column filter. So for example, if I choose the product column to filter, I draw a line, it will affect product and fTransactions. The second way that this diagram can help us is that it can tell us which columns will be affected by a table filter. We can clearly see in the expanded table here, every single column will be affected when we use fTransaction, either inside of something like ALL, where we remove all the filters, or when we use it as a table filter to go backwards across a many to one relationship. And then finally, being able to see all the columns in an expanded table means you can use any of these columns when you build a DAX formula. Now, for our last example about how to use CALCULATE to change the filter context, we're going to use this Excel workbook here. I've already built a pivot table, year, month, total revenue. And our goal is to calculate last year's sales, last month's sales, and then calculate year-over-year percentage change. Over here in the measured grid, we're going to calculate last year revenue. Calculate total revenue. And in the filter argument, we're going to change the filter context with the Time Intelligence function-- and this is one of the coolest functions in DAX-- same period last year. Now, all it needs is ddDate, the unique list of dates from the date table. Now, Time Intelligence functions require that you have a date table. They do not work unless you have a date table. So we use the date, close parentheses. And here's what this amazing function does. It sees the external filter context, whether it's a day, a month, or a year, and it jumps back, gets the correct dates, and delivers them as a valid list of dates to calculate. Those dates filter the fact table, and then total revenue is calculated. Close parentheses and Enter. Now we can drag our measure down to the values. And look at that. It got the correct amount for last January. Here it got the correct amount for last year. The grand total cell is incorrect, but we're not going to use this column in our final pivot table. In our final percentage change formula, we'll fix that grand total cell. Now, for last month revenue, we're using CALCULATE total revenue. And to change the filter context, we'll use another Time Intelligence function. This is my second favorite, DATEADD. If you know Excel, this is like a super charged EDATE function. The first argument dates we put are date column, comma, number of intervals, forwards, backwards. We're going backwards, so I want to go back one month. And here's how the DATEADD is like a super charged EDATE function in Excel. We can do day or we can jump back month, quarter, or year. If you remember the EDATE in Excel, we can only jump back a certain number of months, or back or forward a certain amount of months. So I'm going to type month, and that will do a close parentheses, close parentheses. DATEADD, we'll see the current filter context, take those dates, jump back a month, and deliver a valid list of dates for calculate. And I hit Enter, here's our new measure. We drag it down to values, and there we go, last month, last month. Now, we don't want anything in the Year row, because we don't have any last year. And we don't want anything in the grand total. So we're going to have to amend this formula. And the way we're going to do that is I'm going to ask the question, hey, Month column, are you filtered? True. True. There will be a false here because all the months are present. Same in grand total. Here's our measure. Is Month filtered? Is filtered. And we're going to use ddMonth, close parentheses, and Enter. To see how it works, we'll drag it down to the values. This is not something that we would use in a final report, but there it is. Are you filtered for the month? False. False, all the way down to grand total. If is filtered dd, there's our month. Close parentheses. If it's true, then please give me the formula. Otherwise, when we leave this argument out, an if, it will put in a blank. close parentheses and Enter. Now, if we go over to our pivot table, that is looking beautiful. We don't need this one, so I uncheck. Now, our next measure is going to be comparing total revenue and last year revenue and figure out the percentage change from one period to the next. So right here, I need to compare the difference between these two to whatever last year revenue was. Down here in the Year row, I need to figure out the difference and compare it to last year revenue for percentage change. Now, before we jump over to the data model and create our measure, I want to think about how we would actually make this percentage change calculation in an Excel spreadsheet as compared to a DAX measure. Now, in an Excel Spreadsheet, if I'm creating a formula here, I can refer to this cell right here and any other cell in the column. For DAX, we can't actually jump back a few cells. We have to do something like calculate the actual amount as a separate formula. So when we get to calculating the percentage change for February, the measure is going to have to have total revenue and a separate measure for last year revenue. But with Excel, if I have a single column, I can refer to February and February from the previous year. So the formula for percentage change, this year's amount minus last year's amount, close parentheses, divide by and compare it to last year's amount, and Enter. And not only that, but I can certainly copy this formula down. So there it is, 1.9% change between November last year and this year minus 5% from last year, February, to this February. In DAX, we actually had to create this measure to bring last year's amount down to the same row or cell on the pivot table, so this formula, this year minus last year, and we compare it to last year. So for people coming from Excel, sometime we are used to being able to refer to anything everywhere in our spreadsheet. In DAX, it doesn't always work that way. Now, let's go over and create our measure. Now, over in the measure grid, we'll call this Percentage Change. And we're going to start with divide. In the numerator, I take this year's sales and I subtract last year's revenue. Numerator, comma, and we're going to compare it to last period's amount, last year revenue, close parentheses, and Enter. We'll add some percentage number formatting. There it is. we'll drag it down to values. And look at that. We have our correct percentages all the way down to the grand total. We need to turn that off there because that's not correct. Also, we want to notice something. There's nothing showing up here. If we look back up at our measure, the third argument of divide is if the denominator, last year revenue, is equal to zero, then you get a divide by zero error. But this function DIVIDE is programmed, if that's the case, to put a blank in. Now, the way we're going to turn off the grand total cell is we're going to think about the Year column. The Year column has one value everywhere. For all of these months it's 2007, for the total, it's 2007, and so on all the way down to the grand total. The grand total is the only cell where there are multiple years. So we're going to ask the logical question, hey, Year column, do you have one value? All of these will be true. The only one that won't will be the grand total. So up in the formula bar, the if function, and then HASONEVALUE. HASONEVALUE is oftentimes the function you want to use when you want a false in the grand total cell. DD down to year, close parentheses, comma. So in logical test, true everywhere except for the grand total cell. So then we run this. And just like DIVIDE, the IFs, third argument, will put a blank in when there are errors. So DIVIDE and IF over here in DAX do some things that we can't do over in Excel. Close parentheses. And by the way, the blank-- and we mentioned this earlier-- is not like a double quote, double quote, zero length text string that we use in Excel. That's actually considered text. When we use the BLANK function, or use the third argument in IF, or the third argument in DIVIDE, it actually puts blank in, which is like an empty cell or a null value. It is not a zero length text string. So when I hit Enter, over here I see blank because, of course, there is no external filter context, so it's seeing all the years. Over in our pivot table, there it is, blank, and also blank up here. Here's page 39 from our PDF notes, the DAX Formula Evaluation Context Summary. Remember, there's two evaluation contexts, row context and filter context. The CALCULATE and CALCULATETABLE functions do two things. They can change the filter context and perform context transition. Remember, all measures have a hidden CALCULATE function wrapped around them. There are two types of filter contexts before we get to the final filter context, external filter context and internal filter context. And when those two are merged into the final filter context, three operators are used-- intersect OR/AND logical tests, the overwrite operation, and the remove operator. And when considering when to use the KEEPFILTERS, we have to look out for complex filters that exist in the external filter context. And the same columns are used in the first argument of an iterator. ALLSELECTED, remember, that removes the last filter generated from context transition. And when the last filter generated by context transition is the row context in a pivot table, then ALLSELECTED can help to calculate the correct filtered grand total amount. And remember, column filters work on just columns, and table filters work on the expanded table and can go backwards across a one to many relationship. Wow. That was an epic video all about the CALCULATE and CALCULATETABLE DAX function, filter context, and, of course, ALLSELECTED and KEEPFILTERS, too, in both Power BI Desktop and Excel PowerPivot. Now, if you like that video, be sure to click that thumbs up, leave a comment, and subscribe, because there's always lots more videos to come from excelisfun. And we'll see you next video. If you like what you see in this video, click that subscribe button and the bell icon to get notified about new videos.
Info
Channel: ExcelIsFun
Views: 88,634
Rating: undefined out of 5
Keywords: Excelisfun, Highline College, Data Analysis, Business Intelligence, BI 348, Mike Girvin, Microsoft Power Tools for Data Analysis 19, MSPTDA 19, CALCULATE DAX Function, CALCULATE, Filter Context, Overwrite Operation DAX, Understanding Filter Context, DAX Frequency Distribution, ALLSELECTED DAX, KEEPFILTERS DAX, Understanding KEEPFILTERS, AND Logical Test, Context Transition, Free DAX Class, Learn DAX, Learn Filter Context, How Does Filter Context Work?, What is Filter Context
Id: wQT3vbNpETc
Channel Id: undefined
Length: 108min 27sec (6507 seconds)
Published: Fri Feb 01 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.