DAX Filter context - excel

I am wondering what the difference is between these two DAX expressions which each return what I need:
(1) =calculate([PctMkt], FILTER ( ALL ( BondDim), BondDim[Quality] = "HY" ))
(2) =calculate([PctMkt], ALL(BondDim), BondDim[Quality] = "HY" )
Does the DAX engine make these two expressions equivalent? Is (2) just short hand for (1)? Also, would (1) calculate more quickly? Trying to make sure that I don't cause problems in the pivot table by "hacking" together calculated measures. These measures allow the user to drilldown to a lower grain while keeping higher level data in context of the pivot table.

A simpler, similar question is well-known.
CALCULATE (
[PctMkt],
BondDim[Quality] = "HY"
)
is the shortened equivalent of
CALCULATE (
[PctMkt],
FILTER (
ALL ( BondDim[Quality] ),
BondDim[Quality] = "HY"
)
)
Your formulas need a bit more thought.
When ALL is used as an argument of CALCULATE, it only removes filters (like REMOVEFILTERS) rather than acting as a table expression.
When ALL ( < table > ) is used as an argument of FILTER, it is necessarily a table expression.
The first link I gave gives a detailed example of how this distinction can make an important difference. I'll provide another example here:
Suppose MarketDim has a one-to-many relationship with BondDim (and is not bidirectional) on the ID column from each and the tables are as follows:
BondDim MarketDim
Quality ID ID Pct
------------- ----------
HY 1 1 5%
VY 1 2 10%
XY 2 3 20%
Let's suppose [PctMkt] := MAX ( MarketDim[Pct] )
Then, in your first formula (1), the FILTER argument is the following table:
Quality ID
-------------
HY 1
Thus, the result of (1) can only be 5% (or blank) since ID = 1 is the only option.
In your second formula (2), there are no table arguments since ALL ( BondDim ) is only removing filters and BondDim[Quality] = "HY" only acts on a single column. Without table arguments, since MarketDim filters BondDim but not vice versa (since it's a single direction relationship), neither of these column filter arguments has any effect on the measure I've defined (it might on your actual measure though).
Thus, the result of (2) is the same as just CALCULATE ( [PctMkt] ), which will be 20% unless there is filtering on MarketDim to exclude ID = 3.
Note: This simplification for (2) does not hold if [PctMkt] operates on BondDim columns or any table columns that are filtered by BondDim in your model. I.e. the filters propagate "downstream" across relationships but not "upstream".

The second one
CALCULATE (
[PctMkt],
ALL ( BondDim ),
BondDim[Quality] = "HY"
)
is internally expanded by DAX as the equivalent formula
CALCULATE (
[PctMkt],
ALL ( BondDim ),
FILTER (
ALL ( BondDim[Quality] ),
BondDim[Quality] = "HY"
)
)
So it is not the same as the first one
CALCULATE (
[PctMkt],
FILTER (
ALL ( BondDim ),
BondDim[Quality] = "HY"
)
)
The difference is that the first one uses the whole BondDim table as a filter while the second one is using just one column of the same table

Related

Max(If( equivalent in DAX PowerPivot

This question has been asked and answered before, however the solutions I've found don't seem to work for my current situation.
My table looks like:
I want to return the highest value in column B for all instances of it's match in column A in power pivot.
With a standard excel function, I would use =max(if(a2=a:a,b:b)) in column C.
I've tried =CALCULATE(max(Table1[B]),filter(Table1,Table1[A]=Table1[A])) but this is the result
Any help would be appreciated!
Table1[A] always equals Table1[A] so your condition is always true and thus doesn't do any meaningful filtering.
What you're looking for is to filter by the earlier row context (from the original table, not the FILTER iterator function):
CALCULATE (
MAX ( Table1[B] ),
FILTER ( Table1, Table1[A] = EARLIER ( Table1[A] ) )
)
Another way to do this is to use a variable to grab the row context before you're inside of the FILTER.
VAR CurrRowA = Table1[A]
RETURN
CALCULATE ( MAX ( Table1[B] ), Table1[A] = CurrRowA )

Return DAX Measure created from Table VAR that ignores filter context

I have a table that looks like this:
I've loaded this into Excel PowerPivot and am trying to create a normalized/indexed column that I can use in pivot table. For reasons I wont go into, I'm trying to do this via a Measure vs a Calculated Column.
Here is the code for my Measure:
Measure 1:=VAR Group1 = GROUPBY('Test','Test'[Country],'Test'[Date],"Visits1", SUMX(CURRENTGROUP(),'Test'[Visits])) VAR Group2 = GROUPBY(Group1,[Country],"Visits2", MAXX(CURRENTGROUP(),[Visits1])) RETURN CALCULATE(MAXX(Group2,[Visits2]),ALL('Test'[Date]))
I'm pretty novice with DAX, but this is what I assume is happening when I create my Table VARs:
Using this Measure, when I go and create a Pivot Table, I get this (I've manually added the yellow columns):
As you can see, 'Measure 1', does not equal my 'Expected' column. I've tried a whole bunch of ways to use ALL() in my RETURN statement, but I cannot get it to work. Can anyone help?
Oh, and once I achieve this my goal was to indexed value as seen in my final yellow column using the pseudo formula below.
Row value / Max column value (but filtered by country) * 100
[measure] :=
VAR MaxVisits =
CALCULATE (
MAXX ( VALUES ( Visits[Date] ), CALCULATE ( SUM ( Visits[Visits] ) ) ),
ALL ( Visits[Date] )
)
VAR CurrentVisit =
CALCULATE (
MAXX ( VALUES ( Visits[Date] ), CALCULATE ( SUM ( Visits[Visits] ) ) )
)
VAR Ratio =
DIVIDE ( CurrentVisit, MaxVisits ) * 100
RETURN
Ratio

How to add an if statement in a DAX formula measure?

I am new to DAX and have created two measures to get the total pay per employee then lookup that total pay into a table and return a value in my Power Pivot.
Total Pay Measure:
NMRPaySum:=SUMX(Pay,[Regular Pay]+[Overtime Pay]+[Other Pay])
Range Lookup Measure:
SSSContributionEE :=
CALCULATE (
VALUES ( SSSContribution[EE] ),
FILTER (
SSSContribution,
[NMRPaySum] >= SSSContribution[Lower Bound] &&
[NMRPaySum] <= SSSContribution[Upper Bound]
)
)
However, I need the range lookup to only calculate if the employee type is satisfied.
The logic for it is below:
If Employee[Type]="Regular" Then
Calculate SSSConbtributionEE
Else
0
End If
I have tried this DAX formula, but doesn't seem to be working:
=
IF (
OR ( Salary[Type] = "Regular", Salary[Type] = "Agency" ),
CALCULATE (
VALUES ( SSSContribution[EE] ),
FILTER (
SSSContribution,
[NMRPaySum] >= SSSContribution[Lower Bound] &&
[NMRPaySum] <= SSSContribution[Upper Bound]
)
),
0
)
NMRPay Table:
SSS Contribution Table:
Employee Information Table:
Use your measure as is, for all the data. You then build a Pivot table, where you can use a filter or slicers on Employee Type to exclude unwanted values. Add the measure to the Values area and it will only calculate for data that is in the rows and columns of the pivot table.
For the OR condition, you should be able to add that as another filter:
= CALCULATE (
VALUES ( SSSContribution[EE] ),
FILTER (
SSSContribution,
[NMRPaySum] >= SSSContribution[Lower Bound] &&
[NMRPaySum] <= SSSContribution[Upper Bound]
),
FILTER (Salary, Salary[Type] = "Regular" || SalaryType = "Agency")
)
This may or may not work depending on your exact data model / relationship structure, but it might point you in the right direction. It's possible you need to use RELATED / RELATEDTABLE, but I'm not sure without being able to play with it myself.

Optional FILTER in CALCULATE in DAX

Similarly to the Basket Analysis DAX pattern model, I have 1 fact for Sales, 1 dimension for Product and an extra dimension for Filter Product.
I want to use the Filter Product dimension to exclude products chosen by the user. I made it work with this DAX formula:
Sales =
CALCULATE (
SUM ( Sales['Sales'] ),
FILTER (
Product,
NOT ( 'Product'['ProductName'] IN VALUES ( 'FilterProduct'['ProductName'] ) )
)
)
This works as long as the user has already chosen a Product to exclude on FilterProduct slicer. But if nothing has been selected, the calculation will show blank, rather than just show everything. I wonder if there's a way to handle this gracefully. An idea I had was to create a variable and see if FilterProduct ISFILTERED(). If so, copy&paste the above with the FILTER() on SWITCH statement, if not, just skip the FILTER(). But this isn't great, because it duplicates code, and if I was to add another optional filter (e.g. SalesRegion), I'd had to pre-calculate all the combinations (e.g. SalesRegion & Product, just SalesRegion, just Product, none).
I think you can use the ISFILTERED function, but not exactly how you were suggesting. Try inserting it into you measure like this:
Sales =
CALCULATE (
SUM ( Sales['Sales'] ),
FILTER (
Product,
NOT ( ISFILTERED('FilterProduct'['ProductName']) ) ||
NOT ( 'Product'['ProductName'] IN VALUES ( 'FilterProduct'['ProductName'] ) )
)
)

DAX: Calculate the ratio of Metric A to a sibling Metric B (when both reside in the same group)

I am a complete noob to DAX and OLAP, so please, forgive any errors.
Story
Basically, I have a Matrix component in PowerBI Desktop report.
Months are on the columns, Metrics - on the rows:
The problem arises when I try to calculate the ratio of (percents in red):
Metric B to Metric A (B/A)
Metric C to Metric B (C/B)
All metrics reside in the same group. I wish these ratios be put as a separate, but one column.
I have no problems to calculate Metric ratio to total; I just take SUM(#) and divide by measure Total:
Total = CALCULATE(SUM('Data'[#]); ALL('Data'[Metric]))
Question
But how do I get a SUM(#) aggregate for Metric X which I could later use to calculate the ratio of other metrics?
What I've done so far
As one of the steps I created this table to get the aggregated # for Metric A:
Table = ADDCOLUMNS(
SUMMARIZE('Data';
'Data'[GroupAndMetric];
'Data'[Year];
'Data'[MonthNo]);
"Count";
CALCULATE(SUM('Data'[#]); 'Data'[GroupAndMetric] = "Group A - Metric A")
)
Any help appreciated.
I think there is an easier way to get your expected result but I am assuming your data is exactly the same as the posted in the OP.
Create the following measures to calculate the previous and current values in the given context of each metric.
Sum of [#]:
CurrentValue = SUM(Data[#])
Current Group
CurrentGroup = FIRSTNONBLANK(Data[Group],0)
Current Metric
CurrentMetric = FIRSTNONBLANK(Data[Metric],0)
Current Month:
CurrentMonth = FIRSTNONBLANK(Data[Month],0)
This calculates the previous Metric
PrevMetric =
IF (
[CurrentMetric] = "Metric A",
BLANK (),
IF (
[CurrentMetric] = "Metric B",
"Metric A",
IF ( [CurrentMetric] = "Metric C", "Metric B", BLANK () )
)
)
Calculate the previous metric sum of # necessary for the ratio calculation:
Previous # Sum =
CALCULATE (
SUM ( Data[#] ),
FILTER (
ALL ( Data),
COUNTROWS (
FILTER (
Data,
EARLIER ( Data[Metric] ) = [PrevMetric]
&& EARLIER ( Data[Group] ) = [CurrentGroup]
&& EARLIER ( Data[Month] ) = [CurrentMonth]
)
)
)
)
Finally calculate the ratio:
% Ratio = DIVIDE([CurrentValue], [Previous # Sum])
You will get a bunch of measures but you just have to use the % Ratio in the matrix:
Let me know if this helps.
There are probably (much) better ways of doing this, but here's one way:
To do a metric B divided by metric A (for example):
Metric B to Metric A =
DIVIDE (
CALCULATE ( SUM ( Data[#] ), FILTER ( Data, Data[Metric] = "Metric B" ) ),
CALCULATE ( SUM ( Data[#] ), ALL ( Data[Metric] ), Data[Metric] = "Metric A" ),
BLANK ()
)
The first CALCULATE (the numerator) returns blank if the pivot table isn't filtered to metric B. The second CALCULATE (the divisor) returns the sum of Metric A (following any other filters that are applied, so it won't sum up metric B's that are in another group for example, as long as group is on your pivot table). If we're looking at any metric other than B, this whole division will be BLANK because the numerator will be blank. The final BLANK says that if there are no metric A's (i.e. divide by zero), then the result will also be BLANK.
Assuming 2 measures like this, you could then combine them into a single column:
Final Ratio =
IF (
NOT ( ISBLANK ( [Metric B to Metric A] ) )
&& NOT ( ISBLANK ( [Metric C to Metric B] ) ),
BLANK (),
IF (
NOT ( ISBLANK ( [Metric B to Metric A] ) ),
[Metric B to Metric A],
IF (
NOT ( ISBLANK ( [Metric C to Metric B] ) ),
[Metric C to Metric B],
BLANK ()
)
)
)
This first part says, if both measures are not blank, return a blank (i.e. I don't want a group total that doesn't make sense). Then it goes through each metric and says if it isn't blank, display it. Otherwise, display blank. Since each underlying measure only returns a value for a single given metric, this should work.

Resources