## Understanding Earlier Function in DAX

The DAX EARLIER function is often explained as – “It returns the current row value of a column”

Which is correct.. but partially!

The simplistic definition above does not fully explain the nitty gritties of EARLIER. In this post, I’ll do my best to show you the finer workings of EARLIER. We’ll also take a look some use cases and how to use EARLIER in a Column and in a Measure.

You’re going to stay here for a bit so get a coffee before you start 🙂

**I would highly recommend to use Variables (VAR) instead of the Earlier Function. **

### This is tricky, wanna grab the Video first ?

### EARLIER Syntax

The function accepts 2 inputs

- Column Name
- Number which is optional

Now at the risk of losing you at the start I am going to say something difficult but if you stick around you’d understand every word by the end of this post.

** The Earlier Function returns the value of the Current Row in the Column specified and the EARLIER function at-least needs to have 2 nested ROW Contexts.**

If you din’t understand anything.. that’s okay, you should just remember 2 things and move on.

- Earlier will return the value of the current row in a column.
- To use the Earlier we’ll need to create 2 nested row contexts – and that is the most unexplained part.

### Consider this Sales Table

**Question** – **Create a Column to count the instance for each date**, in other words a COUNTIF on Date Column

- So I’d write 2 since 2nd-Jan-2011 appears twice
- And number 3 for 6th-Jan-2011.. you get the idea!

Let’s solve this using EARLIER

### Using EARLIER in a Column

If start your formula like this = EARLIER ( Sales[Date] ) you’d won’t be able to write the formula since that is deemed invalid. So let’s start differently – consider the following calculated column

Solved. But the question that has personally bothered me for a long time is that..

- Why do I need the FILTER Function to be able to work with EARLIER and
- Why din’t the EARLIER function work when written at the start of the calculated column ?

Remember what I said about EARLIER – **It needs 2 nested ROW Contexts. **Time to explain this

**Step 1** – When you created a Calculated Column in the Sales table you are technically working in a ROW Context and are writing the formula in each row of that Table.

**Step 2 –** When you use the FILTER function in each row of the SalesTable, a nested second row context is created that pulls the entire Sales table (again) in each row of the outside Sales Table

**Step 3 – **Each Date in the second row context (inner Sales Table loop, which is inside the FILTER function) is then compared with the current row Date of the first filter context (outer Sales Table loop).

So EARLIER in essence means the current row of the immediate outer loop.

and that’s how the earlier function works.

### Using EARLIER in a Measure

To be able to meaningfully explain the use case of EARLIER in a Measure consider this Case.

- Along with the sales table I have a Region Expenses Table.
- Which has a one to many relationship with the Sales Table. Sales being on the many side, linked with Region Column.

I have to allocate the Budget Value equally to all the rows of the respective region in the Sales table. For instance, if I filter my sales table for Region = “New Delhi”, I get 476 rows, hence the allocation will be = 20,000/476 for each row of the Sales table.

**Question – Create a Measure that allocates the Budget Value in the Sales Table.**

Consider this Measure

**using Earlier**= SUMX( Sales, 1 / COUNTROWS( FILTER( ALL(Sales), EARLIER(Sales[Region]) = Sales[Region] ) ) * RELATED('Region Expenses'[Budget]) )

My logic will be somewhat like this

- In each row of the Sales Table
- Find the allocation % for each row i.e. 1/476 (eg. for New Delhi)
- Then multiply that allocation % with the Budget Value i.e. 20,000 x 1 / 476 (for New Delhi)

And since to be able to work with the EARLIER Function I need to have 2 nested ROW Contexts, I start by using SUMX and then use FILTER to find the count of total rows that belong to each Region.

An alternative approach (measure) using Variables could be like this

**using Variables**= SUMX( Sales, VAR CurrentRegion = Sales[Region] RETURN 1 / COUNTROWS( FILTER( ALL(Sales), CurrentRegion = Sales[Region] ) ) * RELATED('Region Expenses'[Budget]) )

Another measure to do the same thing using could be done using ALLEXCEPT

**using AllExcept**= SUMX( Sales, DIVIDE( 1, COUNTROWS( CALCULATETABLE( Sales, ALLEXCEPT(Sales,'Region Expenses'[Region]) ) ) ) * RELATED('Region Expenses'[Budget]) )

All doing the same thing 🙂 See the Results

### Using EARLIER in more than 2 nested Row Contexts

Remember at the start of this post, I mentioned that earlier has 2 parts..

.

- Column Name
**Number**– What is that for? Let’s Explore

Consider that I added 2 more tables with no relationships to any other tables

**First Table**

**Second Table**

Notice the column name (Value) is the same in both the above tables and to induce further ambiguity, I’ll add another column to my Sales Table called “Value”. In this column I’ll write my name throughout all the rows.

I then create a test column and write the following DAX

Test = CONCATENATEX( 'First Table', CONCATENATEX( 'Second Table', EARLIER([Value],**2**) & "-" & [Value] ) )

Now notice the results

A couple of interesting (or mundane) things to note..

- The number 2 allows you go outside 2 loops and fetch the current row value of the outer most Sales Table.
- Since there are only 2 nested loops, a number > 2 would result in an error. 1 is by default so we never write that 🙂
- You can also modify the EARLIER part and instead write EARLIEST( [Value] ) which would do the same thing of fetching the current row value of the outer most loop.
- You can also avoid writing the number input by prefixing the name of the table before the column name.

Since the column name was kept the same to induce ambiguity, I on purpose din’t write the preceding table name to help you understand (or probably confuse) with the number input 😀

### You should probably watch the Video again!

**DOWNLOAD POWER BI FILE**

### EARLIER Function – Conclusion

Chances are that you either understood everything that I just explained or none of it. Just remember this – You need to have 2 nested row contexts to be able to work with the EARLIER function, be it in a Column or in a Measure.

Let me know in the comments if you have questions, I’d be glad to help.

### More on DAX!

- Calculate Function Quick Tip – Calculate for Non Blanks
- Financial Year Calendar Table in Power BI
- Slab or Tiered Calculations using DAX
- Sort by Column Examples
- Calculate SAMEPERIODLASTYEAR values for partial year

Learn DAX From Scratch!

#### Topics that I write about...

### Download Smart Ebooks on

Excel and Power BI

##### Chandeep

Welcome to Goodly! My name is Chandeep. On this blog I actively share my learning on practical use of Excel and Power BI. There is a ton of stuff that I have written in the last few years. I am sure you'll like browsing around. Please drop me a comment, in case you are interested in my training / consulting services. Thanks for being around Chandeep

Sours: https://www.goodly.co.in/earlier-function-dax-power-bi/

Hi,

I will try to explain the purpose of EARLIER function using an example.

Assume that we have the following table.

Table Name: USERS

If we need a calculated column that gives the count of other users from the same country against each user, we can use EARLIER function.

UsersFromSameCountry = SUMX ( Users, IF ( EARLIER ( Users[Country] ) = Users[Country], 1, 0 ) )

SUMX will iterate over the table "Users" by creating a row context for every row in the table. i.e. it will iterate over the record of each user from A to F.

Although it looks like we have not created any nested row context in the formula mentioned above, in reality, whenever a calculated column is defined using a DAX formula, the column definition itself creates a row context for evaluating a different value for each row using the same formula. That means, when we defined the calculated column, the formula is executed for each row in the table. As a result, there exists a nested row context. One created by the calculated column definition and one created by the aggregation function - SUMX.

The table Users has 6 pairs of User-Country combinations A-X,B-X,C-X,D-Y,E-Y,F-Z and therefore for each pair, the SUMX will iterate over the table Users to count the number of users from the same country. For the first pair, the IF condition is executed 6 times.

The result of SUMX for the first row context (A-Z pair) will be 3. Similarly the SUMX will iterate over the table Users 5 more times for each of the remaining User-Country pairs.

If you look at the example given in the table above, the IF condition is comparing the Users[Country] field with itself, but only the row context varies.

Had we written the formula as...

SUMX ( Users, IF ( Users[Country] = Users[Country], 1, 0 ) )Then the IF condition would always be true and the result of SUMX will always be 6 for each row in the table.

By writing the formula as

SUMX ( Users, IF ( EARLIER ( Users[Country] ) = Users[Country], 1, 0 ) )We will be able to compare the value of Users[Country] field of SUMX's iteration with each row in the table (row context created by the calculated column definition) and thereby giving the correct result as follows...

In short, EARLIER is used to refer to the outer row context in case of a nested row context. The nesting of row contexts can be done either explicitly writing a DAX code by the user or by the DAX engine when an aggregate function is used in the calculated column definition.

## How To Use The EARLIER Function In Power BI – A DAX Tutorial

Most DAX beginners and even intermediate users really struggle in understanding what the **EARLIER****function** does. It also took me a long time to understand how, when and why you should use this function in Power BI. **You may watch the full video of this tutorial at the bottom of this blog.**

In this article, we are going to complete a deep dive into using the **EARLIER function**. I’ll show you examples of how we can use this function effectively.

Also, I’ll be showing you a much more intuitive way to run calculations instead of using the **EARLIER function** at all.

**Download Free Resources Here**

### How & When To Use The EARLIER Function

Historically the EARLIER function was the only way to manipulate the context of a calculation within a particular formula. But since VARIABLES were introduced, it is now not as essential as it once was.

However, understanding

EARLIERis important if you want to take your DAX knowledge up to a new level. It requires a thorough understanding of row and filter context, which are vital concepts when working with DAX calculations.

For a quick revision of the general (but very important) concept of context see the links below.

**Evaluation Context – (1.8) Ultimate Beginners Guide to DAX**

**Filter Context – (1.9) Ultimate Beginners Guide to DAX**

**Explaining Row Context – (1.10) Ultimate Beginners Guide to DAX**

I’ll be using the Products table for all of the examples we run through here. If we take a quick look at the model you will see that my Products table is a lookup table with a relationship down to my Sales table (which is considered a fact table).

I want to calculate some cumulative totals within this particular table.

The first cumulative total is a generic one. I wanted to calculate it just based off a general index that I have for each product which is derived from the Product Name that I have in this particular table.

The next thing I did is place the Total Product Sales inside the Total Sales measure. One key concept of this particular formula is **context transition**.

#### Context Transition And Row Context

Context transitionoccurs by placing a measure inside of the expression. And then you are able to move from a row context to a filter context.

That’s how this particular result is filtered for Product 1.

I dived into that because understanding context in a table and a calculated column is key here. And in this particular case, we’re using **row context**.

Row contextmeans that an evaluation is going to happen at every single row. And every single row in a calculated column has a result with the evaluation that’s happening at every single row.

### Cumulative Total Examples Using The EARLIER Function

Now, I want to calculate a cumulative total based on this particular row in the Cumulative Product Sales column, and I want to do it in a calculated column. This is where **EARLIER** comes into play.

The formula for this example contains the **FILTER** function. And in this particular formula, **FILTER** adds an additional row context.

We started with a** Row Context** for this calculation and then used the **Filter Function** which will evaluate through every single row in the product table.

And then in every single row in the Product table, we look at what the index is and evaluate if it is less than a specific number that we have in the row.

#### Scenario 1: Product Index Is Less Than Or Equal To 8

For this particular row, we want to calculate everything that has an index of 8 or below.

We need to evaluate through every single row in the Products table and work out if there is an index number less than or equal to 8.

If there is, then we want to calculate all the sales for those particular products. And as we go down, it re-evaluates the rates.

EARLIERenables us to jump from one row context to the earlier row context to retrieve a value.

#### Scenario 2: Product Index Is Less Than Or Equal To 10

In our next example, the particular result is 10. We want to evaluate the Product Index at every single row if it is less than or equal to 10.

Now, some of you who are familiar with the cumulative total concept might think that we can use here the **MAX** function instead, since that’s what we do in the generic cumulative total pattern.

But if I put a **MAX** in the formula, it will always evaluate to the maximum products. Also, it doesn’t actually evaluate the product index at the particular row.

So we need to get out of this **row context** and then jump back to the very initial row context to retrieve the Product Index. And that is what** EARLIER** does.

The

EARLIERfunction allows us to jump from one context to a prior row context, so we can grab the result that we want.

#### Scenario 3: Using Product Ranking Instead Of Product Index

For our next example, I’ve ranked my products based on sales. I’ve also got a rank based on where they all sit.

The top ranked sales for our products is $864,000 and that’s Product 63.

Now, I want to create a cumulative total based on the ranking. Instead of looking at the earlier index, I’m actually looking for the earlier product sales ranking.

So we have to go through every single product in this particular product table to evaluate if the product ranking is less than or equal to the product ranking on that particular row.

EARLIERis jumping out of this row context and jumping back to the initial row context created by being in a calculated column.

### A Better Alternative To The EARLIER Function

Using **EARLIER** function can be a little complicated. But the good news is we have a better way to do these calculations in Power BI.

**VARIABLES is a far superior way to do the calculations.** I’ll show you how you can bypass **EARLIER**.

In this example, instead of jumping out of the row context created by a filter, we can actually just retrieve the Product Index value in its initial row context in a variable.

So I took **EARLIER** out and put in the **variable ProductIndex**.

You will see here that the Cumulative Product Sales now works perfectly in this new format as well. It looks like how it did before.

We can do exactly the same with the Cumulative Product Sales by Ranking using this calculation:

And then if we sort the Product Sales Ranking column from ascending, we can see that the highest ranked product is Product 63.

### Conclusion

Using **VARIABLES** is a far superior way to tackle all the examples that I’ve shown earlier.

And to be honest, with all the development work that I’ve done before, I rarely used the **EARLIER** function. But it is still a cool function to know and understand.

Variablesare key when you write DAX in many different areas of Power BI. This is where things become a lot simpler.

Instead of having to jump in and out of context within formulas, you can actually initiate the calculations within variables or isolate the calculation with variables in it, so the execution of a formula is more seamless.

You can browse through these links to get more information on this topic:

**Formula Syntax, Comments & Variables – Ultimate Beginners Guide to DAX**

**How To Use Variables in DAX Formula with Power BI**

Hopefully, you can get a good understanding of how this particular calculation operates inside Power BI.

Sam

**Download Free Resources Here**

******* Related Links *****Simple Filters w/CALCULATE – Ultimate Beginners Guide to DAX**

**How To Calculate Budget Or Forecast Results Cumulatively In Power BI**

**Compare Multiple Metrics Cumulatively in Power BI using DAX**

******* Related Course Modules*****Mastering DAX Calculations**

Solving Analytical Scenarios w/Power BI & DAX

Financial Reporting w/Power BI

Solving Analytical Scenarios w/Power BI & DAX

Financial Reporting w/Power BI

******* Related Support Forum Posts *****Cumulative Total Vs Cumulative Total LY – Cleaning Visual**

Cumulative Total Question

Cumulative Total Question

Cumulative Total This Year vs Last

Cumulative Total This Year vs Last

For more cumulative total support queries to review see here…..

For more cumulative total support queries to review see here…..

Tags: Advanced DAX, context transition, Cumulative totals DAX, earlier function, MAX DAX, Row Context, Variables, variables function

### Published by Sam McKay, CFA

Founder, Enterprise DNA View all posts by Sam McKay, CFA

## Cracking DAX – the EARLIER and RANKX Functions

**The series so far:**

- Creating Calculated Columns Using DAX
- Creating Measures Using DAX
- Using the DAX Calculate and Values Functions
- Using the FILTER Function in DAX
- Cracking DAX – the EARLIER and RANKX Functions
- Using Calendars and Dates in Power BI
- Creating Time-Intelligence Functions in DAX

If you really want to impress people at DAX dinner parties (you know the sort: where people stand around discussing row and filter context over glasses of wine and vol-au-vents?), you’ll need to learn about the function (and to a lesser extent about the function). This article explains what the function is and also gives examples of how to use it. Above all, the article provides further insight into how row and filter context work and the difference between the two concepts.

### Loading the Sample Data for this Article

As for the other articles in this series, the sample dataset consists of four simple tables which you can download from this Excel workbook:

After importing the data, you should see this model diagram (I’ve used Power BI, but the formulae in this article would work equally well in PowerPivot or SSAS Tabular):

One more thing to do – add a calculated column to the country table, giving the total sales for each country:

1 | TotalSales=CALCULATE(Sumx(Sales,[Price]*[Quantity])) |

This formula iterates over the *Sales* table, calculating the sales for each row (the quantity of goods sold, multiplied by the price) and summing the figures obtained. The function is needed because you must create a filter context for each row so that you’re only considering sales for that country – without it, you would get this:

### Example 1: Ranking the Countries

The first use case is very simple. The aim is to rank the countries by the total sales for each:

DAX doesn’t have an equivalent of the SQL clause, but you can rank data either by using the function (covered later in this article) or by using the function creatively. Here’s what the function needs to do, using country number 3 – India – as an example. Firstly, it creates a row context for this row:

The sales for India are 34.5. What it now must do is to count how many rows there are in the table which have countries whose sales are greater than or equal to India’s sales:

This shows the filtered table of countries, including only those whose sales are at least equal to India’s. There are four rows in this filtered table.

If you perform the same calculations for each of the other countries in the table, you’ll get the ranking order for each (that is, the number of countries whose sales match or exceed each country’s). For those who know SQL, this works in the same way as a correlated subquery. This would imply that it might run slowly, however, here’s what Microsoft have to say on the subject:

### The problem: One Row Context Hides Another

Anyone who has driven much in France will have seen this sign at a level-crossing:

What it means is “one train can hide another” … and so it is with row contexts. The measure will open two row contexts, as the diagram below shows:

The problem is that when DAX gets to the inner row context for the function, it will no longer be able to see the outer row context (the country you’re currently considering) as this row context will be hidden unless you use the function to refer to the first row context created in the formula.

### What Would You Name this Function?

I’ve explained that the function refers to the original row context created (nearly always for a calculated column). What would you have called this function? I’d be tempted by one of these names:

- OUTERROWCONTEXT
- PREVIOUSROWCONTEXT
- INITIALROWCONTEXT

The multi-dimensional (cubes) version of Analysis Services gets it about right, using and depending on context. It’s interesting to see that you can’t use these words as names of variables in DAX as they are reserved words:

This is true even though they aren’t official DAX function names!

What I definitely wouldn’t use for the function name is something which implied the passage of time. To me, means something which occurred chronologically before something else. I think this is one of the reasons it took me so long to understand the function: it’s just got such an odd name.

### The Final Formula Using EARLIER

Having got that off my chest, here’s the final formula:

SalesOrder=COUNTROWS( Filter( Country, [TotalSales]>=EARLIER([TotalSales]) ) ) |

Here’s the English (!) translation of this …

“For each country in the countries table, create a row context (this happens automatically for any calculated column). For this row/country being considered, count the number of rows in a separate virtual copy of the table for which the total sales for the country are greater than or equal to the total sales for the country being considered in the original row context”.

What could possibly be confusing about that?

### Other Forms of the EARLIER Function

Readers will be delighted to know that you don’t have to limit yourself to going back to the previous row context – you can specify how many previous row contexts to return to by varying the number used in the second argument to the function:

You can even use the function to go to the earliest row context created for a formula. The formula could alternatively have been written like this:

SalesOrder=COUNTROWS( FILTER( Country, [TotalSales]>=EARLIEST([TotalSales]) ) ) |

I find it very hard to believe that anyone would need this function! It could only be useful where you:

- Create a row context (typically by creating a calculated column).
- Within this, create a filter context.
- Within this, create a row context (typically by using an iterator function like or ).
- Within this, create another filter context.
- Within this, create a third-row context.

In this complicated case, the function would refer to the row context created at step 3, but the function would refer to the original row context created at step 1.

### Avoiding the EARLIER Function by Using Variables

One of the surprising things about the function is that you often don’t need it. For this example, you could store the total sales for each country in a variable, and reference this instead. The calculated column would read instead:

Sales order usingvariables= // create a variable to hold each country's sales VARTotalSalesThisCountry=[TotalSales] // now count how many countries have sales // which match or exceed this RETURNCOUNTROWS( FILTER( Country, [TotalSales]>=TotalSalesThisCountry ) ) |

There’s not much doubt that this is easier to understand, but it won’t give you the same insight into how row context works!

### Using the EARLIER function in a measure

The function refers to the previous row context created in a DAX formula. But what happens if there isn’t a previous row context? This is why you will so rarely see the function used in a measure. Here’s what you’ll get if you put the formula in a measure:

The yellow error message explains precisely what the problem is: measures use filter context, not row context, so no outer row context is created.

### Example 2: Running Totals

Another common requirement is calculating the cumulative total sales for countries in alphabetical order:

The above screenshot shows that this calculates the answer separately for each country, but it looks more sensible when you view it in alphabetical order by country name:

The formula for this column calculates for each country the total sales for all countries coming on or before it in alphabetical order:

Running total=SUMX( FILTER( Country, Country[CountryName]<=EARLIER(Country[CountryName]) ), [TotalSales] ) |

Again, you could have alternatively used a variable to hold each country’s name:

Running total usingvariables= // store this row's country name VARThisCountry=Country[CountryName] // return the sum of sales for all countries up to or // including this one RETURNSUMX( FILTER( Country, Country[CountryName]<=ThisCountry ), [TotalSales] ) |

### Example 3: Group Totals

Here’s another use of the function – to create group totals. To follow this example, first, add a calculated column in the Sales table to show the name of each product bought (you don’t have to do this, but it will make the example clearer if you use the product name rather than the product id to match sales rows to the product bought):

Product = RELATED(‘Product'[ProductName])

Here’s the column this should give:

You can now create a second calculated column:

Average product sales=AVERAGEX(
// average over the table of sales records for the // same product as this one ... FILTER(Sales,[Product]=EARLIER(Sales[Product])),
// ... the total value of the sale [Price]*[Quantity] ) |

Here’s what this will give for the first few roles in the *SALES* table. You may want to format the column as shown by modifying the decimal places on the Modeling tab.

The group average for Olly Owl products is 5.40. For this example, for each sales row, the calculated column formula is averaging the value of all sales where the product matches the one for the current row.

### Example 4: Creating Bands

So far, you have seen three relatively simple uses of the function – for the fourth example, I’ll demonstrate a more sophisticated one. Begin by adding a calculated column to the *Sales* table, giving the value of each transaction (which should equal the number of items bought, multiplied by the price paid for each):

It would be good to categorise the sales into different bands, to allow reporting on different customer bands separately. For example:

- Any purchase with value up to £10 is assigned to “Low value”
- Any purchase with value between £10 and £15 is assigned to “Medium value”
- Any purchase with value between £15 and £20 is “High value”
- Any purchase of more than £20 is “Premium customer”

One way to do this would be to create a calculated column using a function like this:

Customer type=SWITCH( // try to find an expression which is true TRUE(), // first test - low value [SalesValue]<=10,"Low value", // second test - medium value [SalesValue]<=15,"Medium value", // third test - high value [SalesValue]<=20,"High value", // otherwise, they are a premium customer "Premium customer" ) |

This would allow reporting on the different customer types (for example, using this table):

However, this hard-codes the thresholds into the calculated column. What would be much more helpful is if you could import the thresholds from another table, to make a dynamic system (similar to a lookup table in Excel, for those who know these things).

### Creating the Table of Bands (Thresholds)

To create a suitable table, in Power BI Desktop choose to enter data in a new table (you could also type it into Excel and load the resulting workbook):

Type in the thresholds that you want to create, and give your table the name *Categories*:

Note that in your model’s relationship diagram, you will now have a data island (a table not linked to any other). This is intentional:

### Creating a Formula Assigning Each Sale Row to a Category

You can now go to the *Sales* table and create a calculated column assigning each row to the correct category:

For each row, what you want to do is find the set of rows in the *Categories* table where two conditions are true:

The lower band for the category is less than the sales for the row; and

The upper band for the category is greater than or equal to the sales for the row.

It should be reasonably obvious that this set of rows will always exist, and will always have exactly one row in it. Because of this, you can use the function to return the value of this single row, giving:

Category=CALCULATE( // return the only category which satisfies both of // the conditions given VALUES(Categories[CategoryName]), // this sales must be more than the lower band ... Categories[Low]<EARLIER(Sales[SalesValue]), // ... and less than or equal to the higher band Categories[High]>=EARLIER(Sales[SalesValue]) ) |

You might at this point wonder why you need the function when you haven’t created a second row context. The answer is that the function creates a filter context, so you need to tell your formula to refer back to the original row context you first created in the formula.

### Sorting the Categories

One problem remains: the categories aren’t in the right order (I’m well aware that one way to solve this would be to click on the column heading to change the sort order, but I’m after something more dynamic!):

To get around this, it may at first appear that all you need to do is to designate a sort column:

You could do this by selecting the *CategoryName* column in the *Categories* table as above, and on the *Modeling* tab, setting this to be sorted by the *SortOrder* column. This looks promising – but doesn’t work (it actually creates an error if you’ve typed in the data for the categories table, which you’ll need to refresh your model to clear). The reason this doesn’t work is that the alternative sort column needs to be in the same table as the *Category* column.

A solution is to create another calculated column in the *Sales* table:

Category SortOrder=CALCULATE( // return the sales order for the two conditons VALUES(Categories[SortOrder]), // this sales must be more than the lower band ... Categories[Low]<EARLIER(Sales[SalesValue]), // ... and less than or equal to the higher band Categories[High]>=EARLIER(Sales[SalesValue]) ) |

You now have two columns for each sale row – one giving the category, and one giving its corresponding sort order number. You can select the category column and choose to sort it using the sort order column instead (choosing the option shown below on the Power BI Modeling tab):

Bingo! The categories appear in the required order:

If after reading this far you’re still a bit fuzzy on the difference between row and filter context, practice makes perfect! I’ve found reading and re-reading articles like this helps, as each time you get closer to perfecting your understanding (for those in the UK, you could also consider booking onto one of Wise Owl’s Power BI courses).

### Using the RANKX Function to Rank Data

Out of all the DAX functions, the one which trips me up most often is – which is odd, because what it does isn’t particularly complicated. Here’s the syntax of the function:

So the function ranks a table by a given expression. Here is what the arguments mean:

- The Table argument gives the table you’re ranking over.
- The Expression argument gives the expression you’re ranking by.
- The Order column allows you to switch between ascending and descending order.
- The Ties column lets you specify how you’ll deal with ties.

You’ll notice I’ve missed out the Value argument. This is for the good reason that it is a) bizarre and b) not useful. It allows you to rank by one expression, substituting in the value for another for each row in a table. If this sounds like a strange thing to want to do, then I’d agree with you.

To see how the function works, return to the *Country* table in which you created a calculated column at the beginning of this article:

Suppose you now want to order the countries by sales (clearly one way to do this would just be to click on the drop arrow next to the column and choose *Sort* ascending!). Here’s a calculated column which would do this:

What you should notice is the unusual default ranking order: unlike in SQL (and many other languages), the default order is descending, not ascending. To reverse this, you could specify ASC as a value for the fourth Order argument:

Sales order=RANKX(
// rank the rows in the country table ... Country,
//... by the total sales column ... [TotalSales],
// omitting the third argument ,
// and ranking in ascending order ASC ) |

So far, so straightforward!

### Using RANKX in a Measure

Where things get more complicated is when you use in a measure, rather than in a calculated column. Suppose that you have created a table visual like this in a Power BI report:

Suppose further that you want to create and display this measure to show the ranking order:

Sort order measure=RANKX( // order the countries by sales Country, SUMX( Sales, [Price]*[Quantity] ) ) |

However, when you add this measure to your table, you get this:

The reason for this is that Power BI evaluates the measure within the filter context of the table. So for the first row (Brazil), for example, here’s what Power BI does:

- Applies the filter context to the Country table to pick out just sales for Brazil
- Calculates the total sales for this country (14, as it happens)
- Returns the position of this figure within the table of all of the figures for the current filter context (so the returned number 1 means that 14 is the first item in a table containing the single value 14)

To get around this, you first need to remove filter context before calculating the ranking order, so that you rank the total sales for each country against all of the other country’s total sales:

However, even this doesn’t solve the problem. The increasingly subtle problem is that the function – being an iterator function – creates a row context for each country, but then evaluates the sales to be the same for each country because it doesn’t create a filter context within this row context. To get around this, you need to add a function to perform context transition from row to filter context within the row context within the measure:

Sort order measure=RANKX( // order across ALL the countries ... ALL(Country), // by the total sales CALCULATE( SUMX( Sales, [Price]*[Quantity] ) ) ) |

This – finally – produces the correct ranking (note that there is a blank country at the top because some sales don’t have a matching country parent – although this isn’t important for this example):

It’s worth making two points about this. Firstly, this isn’t a formula you’ll often need to use; and secondly, this is about as complicated a DAX formula as you will ever see!

### Dealing with Ties

If your ranking produces ties, the default is to SKIP numbers, but you can also use the keyword to override this. To see what each keyword means, add this calculated column to the *Sales* table:

1 | QtyRanking=RANKX(Sales,[Quantity]) |

What it will do is to order the sales rows by the quantity sold. Here’s what you’ll get if you use Skip, or omit the Ties keyword altogether:

Here, by contrast, is what you’ll get if you use (I’m not quite sure why you’d ever want to do this):

In the second screenshot, there are no gaps in the numbers.

### Conclusion

You can apply the function in various contexts to solve modelling problems in DAX, and it should be an essential part of every DAX programmer’s arsenal. The function, by contrast, solves a very specific problem – ranking data. What both functions have in common is that they are impossible to understand without a deep understanding of row and filter context, so if you’ve got this far, you can consider yourself a DAX guru!

## Earlier function bi power

Returns the value in the column prior to the specified number of table scans (default is 1).

### Syntax

EARLIER ( <ColumnName> [, <Number>] )

Parameter | Attributes | Description |
---|---|---|

ColumnName | The column that contains the desired value. | |

Number | Optional | The number of table scan. |

### Return values

Scalar A single value of any type.

The current value of row, from ColumnName, at Number of outer evaluation passes.

» 2 related articles» 1 related function

### Examples

Yearly Income | Customers | RT Customers |
---|---|---|

10,000 | 1,155 | 1,155 |

20,000 | 1,767 | 2,922 |

30,000 | 2,287 | 5,209 |

40,000 | 2,747 | 7,956 |

50,000 | 670 | 8,626 |

60,000 | 3,127 | 11,753 |

70,000 | 2,349 | 14,102 |

80,000 | 1,342 | 15,444 |

90,000 | 842 | 16,286 |

100,000 | 571 | 16,857 |

110,000 | 474 | 17,331 |

120,000 | 332 | 17,663 |

130,000 | 512 | 18,175 |

150,000 | 103 | 18,278 |

160,000 | 94 | 18,372 |

170,000 | 112 | 18,484 |

10,000,000 | 385 | 18,869 |

Yearly Income | Customers | RT Customers |
---|---|---|

10,000 | 1,155 | 1,155 |

20,000 | 1,767 | 2,922 |

30,000 | 2,287 | 5,209 |

40,000 | 2,747 | 7,956 |

50,000 | 670 | 8,626 |

60,000 | 3,127 | 11,753 |

70,000 | 2,349 | 14,102 |

80,000 | 1,342 | 15,444 |

90,000 | 842 | 16,286 |

100,000 | 571 | 16,857 |

110,000 | 474 | 17,331 |

120,000 | 332 | 17,663 |

130,000 | 512 | 18,175 |

150,000 | 103 | 18,278 |

160,000 | 94 | 18,372 |

170,000 | 112 | 18,484 |

10,000,000 | 385 | 18,869 |

### Related articles

Learn more about EARLIER in the following articles:

**Variables in DAX**In this article, you learn a new feature in DAX 2015: variables. The 2015 version of the DAX language has many new functions, but none of them is a game changer for the language as variables are. » Read more

**DAX coding style using variables**This article shows how variables in DAX can impact the coding style, simplifying a step-by-step approach and improving the readability of your code. » Read more

### Related functions

Other related functions are:

2018-2021 © SQLBI. All rights are reserved. Information coming from Microsoft documentation is property of Microsoft Corp. » Contact us » Privacy Policy & Cookies

### Compatibility

**DirectQuery**

Measures

Calculated columns

**Power BI**v13.0.1700.1022 →

v15.1.110.21Current release

**Excel**v11.0.9165.1186 →

v13.0.1700.1064**SSAS Tabular**v10.50.1600.1 →

v15.1.95.20- SSAS 2012
- SSAS 2014
- SSAS 2016
- SSAS 2017
- SSAS 2019

**Azure AS**v14.0.1.501 →

v15.1.107.21Current release

**SSDT**v14.0.1.432 →

v15.1.80.18Current release

» Show verified builds

### First release

Before 2017-01-01

Sours: https://dax.guide/earlier/## DAX Filter - EARLIER function

### Description

Returns the current value of the specified column in an outer evaluation pass of the mentioned column.

### Syntax

EARLIER (<column>, <number>)### Parameters

Sr.No. | Parameter & Description |
---|---|

1 |
A column or expression that resolves to a column. |

2 |
Optional. A positive number to the outer evaluation pass. - The next evaluation level out is represented by 1.
- Two levels out is represented by 2, and so on.
If omitted, default value is 1. |

### Return Value

The current value of row, from column, at number of outer evaluation passes.

### Remarks

EARLIER is useful for nested calculations where you want to use a certain value as an input and produce calculations based on that input. In Microsoft Excel, you can do such calculations only within the context of the current row. However, in DAX you can store the value of the input and then make calculation using data from the entire table.

EARLIER is mostly used in the context of calculated columns. EARLIER succeeds if there is a row context prior to the beginning of the table scan. Otherwise, it returns an error.

### Example

If you have a table Sales with sales data, you can create a calculated column with the ranks of the Sales Amount values as follows −

= COUNTROWS ( FILTER (Sales, EARLIER (Sales[Sales Amount])<Sales[Sales Amount]) )+1dax_functions_filter.htm

### Similar news:

- Green nail designs
- 5 royal tank regiment
- Setting up synonyms
- Swfa ss for sale
- Posterior acoustic shadowing and enhancement
- Marine parts outlet
- Hollywood spirit day ideas
- 30mm wide scooter wheels

## EARLIER

- 4 minutes to read

Returns the current value of the specified column in an outer evaluation pass of the mentioned column.

EARLIER is useful for nested calculations where you want to use a certain value as an input and produce calculations based on that input. In Microsoft Excel, you can do such calculations only within the context of the current row; however, in DAX you can store the value of the input and then make calculation using data from the entire table.

EARLIER is mostly used in the context of calculated columns.

### Syntax

### Parameters

Term | Definition |
---|---|

column | A column or expression that resolves to a column. |

num | (Optional) A positive number to the outer evaluation pass. The next evaluation level out is represented by 1; two levels out is represented by 2 and so on. When omitted default value is 1. |

### Return value

The current value of row, from **column**, at **number** of outer evaluation passes.

### Exceptions

Description of errors

**EARLIER**succeeds if there is a row context prior to the beginning of the table scan. Otherwise it returns an error.The performance of

**EARLIER**might be slow because it theoretically, it might have to perform a number of operations that is close to the total number of rows (in the column) times the same number (depending on the syntax of the expression). For example if you have 10 rows in the column, approximately a 100 operations could be required; if you have 100 rows then close to 10,000 operations might be performed.This function is not supported for use in DirectQuery mode when used in calculated columns or row-level security (RLS) rules.

Note

In practice, the VertiPaq in-memory analytics engine performs optimizations to reduce the actual number of calculations, but you should be cautious when creating formulas that involve recursion.

### Example

To illustrate the use of EARLIER, it is necessary to build a scenario that calculates a rank value and then uses that rank value in other calculations.

The following example is based on this simple table, **ProductSubcategory**, which shows the total sales for each ProductSubcategory.

The final table, including the ranking column is shown here.

ProductSubcategoryKey | EnglishProductSubcategoryName | TotalSubcategorySales | SubcategoryRanking |
---|---|---|---|

18 | Bib-Shorts | $156,167.88 | 18 |

26 | Bike Racks | $220,720.70 | 14 |

27 | Bike Stands | $35,628.69 | 30 |

28 | Bottles and Cages | $59,342.43 | 24 |

5 | Bottom Brackets | $48,643.47 | 27 |

6 | Brakes | $62,113.16 | 23 |

19 | Caps | $47,934.54 | 28 |

7 | Chains | $8,847.08 | 35 |

29 | Cleaners | $16,882.62 | 32 |

8 | Cranksets | $191,522.09 | 15 |

9 | Derailleurs | $64,965.33 | 22 |

30 | Fenders | $41,974.10 | 29 |

10 | Forks | $74,727.66 | 21 |

20 | Gloves | $228,353.58 | 12 |

4 | Handlebars | $163,257.06 | 17 |

11 | Headsets | $57,659.99 | 25 |

31 | Helmets | $451,192.31 | 9 |

32 | Hydration Packs | $96,893.78 | 20 |

21 | Jerseys | $699,429.78 | 7 |

33 | Lights | 36 | |

34 | Locks | $15,059.47 | 33 |

1 | Mountain Bikes | $34,305,864.29 | 2 |

12 | Mountain Frames | $4,511,170.68 | 4 |

35 | Panniers | 36 | |

13 | Pedals | $140,422.20 | 19 |

36 | Pumps | $12,695.18 | 34 |

2 | Road Bikes | $40,551,696.34 | 1 |

14 | Road Frames | $3,636,398.71 | 5 |

15 | Saddles | $52,526.47 | 26 |

22 | Shorts | $385,707.80 | 10 |

23 | Socks | $28,337.85 | 31 |

24 | Tights | $189,179.37 | 16 |

37 | Tires and Tubes | $224,832.81 | 13 |

3 | Touring Bikes | $13,334,864.18 | 3 |

16 | Touring Frames | $1,545,344.02 | 6 |

25 | Vests | $240,990.04 | 11 |

17 | Wheels | $648,240.04 | 8 |

### Creating a Rank Value

One way to obtain a rank value for a given value in a row is to count the number of rows, in the same table, that have a value larger (or smaller) than the one that is being compared. This technique returns a blank or zero value for the highest value in the table, whereas equal values will have the same rank value and next value (after the equal values) will have a non consecutive rank value. See the sample below.

A new calculated column, **SubCategorySalesRanking**, is created by using the following formula.

The following steps describe the method of calculation in more detail.

The

**EARLIER**function gets the value of*TotalSubcategorySales*for the current row in the table. In this case, because the process is starting, it is the first row in the table**EARLIER**([*TotalSubcategorySales*]) evaluates to $156,167.88, the current row in the outer loop.The

**FILTER**function now returns a table where all rows have a value of*TotalSubcategorySales*larger than $156,167.88 (which is the current value for**EARLIER**).The

**COUNTROWS**function counts the rows of the filtered table and assigns that value to the new calculated column in the current row plus 1. Adding 1 is needed to prevent the top ranked value from become a Blank.The calculated column formula moves to the next row and repeats steps 1 to 4. These steps are repeated until the end of the table is reached.

The **EARLIER** function will always get the value of the column prior to the current table operation. If you need to get a value from the loop before that, set the second argument to 2.

### See also

EARLIEST function

Filter functions

**2340**2341 2342