DAX: Unwanted cartesian product lines? - filter

Please help to calculate/understand properly lastDate and rankDate measures for following simplified example (download):
Desired result:
Reality (incorrect subtypes):
Why relationship is broken?
How to avoid this cartesian product lines?
My Measure (I commented workaround, because it's kind of postfilter, not prefilter):
rnkDate =
VAR t =
CALCULATETABLE(
VALUES(tstTable[Date]),
REMOVEFILTERS(tstTable[Date])
)
RETURN
//IF( MAX(tstTable[Amount])<>BLANK(), // WORKAROUND To hide unwantedd rows
RANKX(
t,
LASTDATE(tstTable[Date])
)
//)
P.S. Mess happens only if I use fields from dimensional table dimType[Type] (within one table everything is Ok):

The problem is that the query generated by Power BI performs the cartesian product and filers the result by checking the result of the measure.
in our case is something similar to
SUMMARIZECOLUMNS(
'dimType'[Type],
'tstTable'[subType],
'tstTable'[Date],
"MinAmount", CALCULATE(MIN('tstTable'[Amount])),
"lastDate", 'tstTable'[lastDate],
"rnkDate", 'tstTable'[rnkDate]
)
SUMMARIZECOLUMNS doesn't use relationships when iterating on different tables, it applies them when evaluating the measures. There is an article explaining what is the equivalent DAX code executed by SUMMARIZECOLUMNS
Introducing SUMMARIZECOLUMNS
the problem is that RANKX evaluated on an empty table retuns 1. This can be seen executing this on dax.do
EVALUATE
VAR t =
FILTER ( ALL ( 'Date'[Date] ), FALSE )
RETURN
{ RANKX ( t, [Sales Amount] ), CALCULATE ( [Sales Amount], t ) }
so the solution is to first check that the table t is not empty, which is the reason because the workaround that you implemented solved the issue
lastDate =
IF( NOT ISEMPTY(tstTable), // checks fact table in particular context
CALCULATE(
LASTDATE(tstTable[Date]),
REMOVEFILTERS(tstTable[Date])
)
)
rnkDate =
VAR t =
CALCULATETABLE(
VALUES(tstTable[Date]),
REMOVEFILTERS(tstTable[Date])
)
RETURN
IF( NOT ISEMPTY(tstTable),
RANKX(
t,
LASTDATE(tstTable[Date])
)
)

Related

Power BI Calculate variance between to rows in the same column dynamically

I am trying to calculate the variance of projects, over different periods.
Periods are referenced as P1, P2,...
The user should be able to pick the periods that they want to compare and see the projects listed
new table
I have tried a dax formula, but I can't find one that has more than one filter.
My DAX:
Variance =
VAR DIFF =
WIP[WIP]
- CALCULATE (
SUM ( WIP[WIP] ),
FILTER ( 'WIP', WIP[Index1] = EARLIER ( WIP[Index] ) )
)
RETURN
IF ( DIFF = VALUE ( WIP[WIP] ), 0, DIFF )
Can you help?
2nd table
Variance =
VAR currentPeriod = SELECTEDVALUE('tbl'[Period])
VAR currentObj = SELECTEDVALUE(tbl[Object])
VAR firstPeriodInSelection=
CALCULATE(
MIN('tbl'[Period])
,'tbl'[Object]=currentObj
,ALLSELECTED('tbl'[Period])
,ALLEXCEPT(tbl,tbl[Period],tbl[Object])
)
VAR prevPeriod =
CALCULATE(
MAX('tbl'[Period])
,'tbl'[Period]<currentPeriod
,'tbl'[Object]=currentObj
,ALL()
)
VAR currentWIP =
CALCULATE(
AVERAGE(tbl[WIP])
,ALLEXCEPT(tbl,tbl[Object],tbl[Period])
)
VAR prevWIP =
CALCULATE(
AVERAGE(tbl[WIP])
,ALLEXCEPT(tbl,tbl[Object])
,'tbl'[Period]=IF(
prevPeriod < firstPeriodInSelection
,firstPeriodInSelection
,prevPeriod
)
)
RETURN
currentWIP-prevWIP
Please, pay attention that on my picture you can see 2 values for one period-object. For this case I used average. So, if it will be one value for period-object then you see the value, if it will be several then you will see calculated Variance for average.

DAX hasonevalue but also total

I have at table where I show a calcutated measure, but in the visulization I only want to show the measures if a specific dimension is in the filter.
This works great with HASONEVALUE:
Dividedmeasure:= IF(HASONEVALUE('Employment'[EmploymentGroup]), DIVIDE([measure1)], [Measure2],(BLANK() )))
The problem is HASONEVALUE also blanks the total which Is not what I want. I want to blank everything where EmploymentGroup is not in the filters since the report doens't make sense without Employmentgroup. Any suggestions?
enter image description here
Try this: I think You should remove BLANK(). Then It won't show anything where [EmploymentGroup] is not inside the filter.
1st Method: HASONEFILTER()
Dividedmeasure =
IF (
HASONEFILTER ( 'Employment'[EmploymentGroup] ),
DIVIDE ( [measure1], [Measure2] ),
)
2nd Method: ISFILTERED()
Dividedmeasure =
IF (
ISFILTERED ( 'Employment'[EmploymentGroup] ),
DIVIDE ( [measure1], [Measure2] )
)

How do I create a DAX expression to display a calculation from a derived table?

I'm using DaxStudio to test some measures, but am having trouble getting them to work. I can run the following expression, but don't know how to run an average of the field Mean to show just the mean of that. I'm basically expecting output to be a single cell with the average.
DAX Query:
EVALUATE
FILTER(
NATURALINNERJOIN(Alldata, NATURALINNERJOIN('Label', NATURALINNERJOIN('LabelBSkill', 'LabelCSkill'))),
'LabelCSkill'[Name] = "Critical"
&& 'Label'[Type]="Red"
)
Mean is in the table Alldata if that matters
Give this a try:
EVALUATE
ROW (
"Mean", CALCULATE (
AVERAGE ( Alldata[Mean] ),
'LabelCSkill'[Name] = "Critical",
'Label'[Type] = "Red"
)
)

DAX: Issues Calculating a Sum with Multiple Filters

I thought I'd reach out for help as I'm having troubles creating a calculated measure in PowerBI. I'm trying to calculate the sum of multiple accounts using filters to grab the correct accounts.
Here is the measure that isn't working:
Measure =
CALCULATE (
SUM ( 'Queryx'[Amount] ),
FILTER (
Queryx,
LEFT ( 'Queryx'[Accnt], 4 )
IN { "8980", "8981", "8982", "8983", "8987", "8988", "8989" }
),
FILTER ( 'Queryx', [Accnt] IN { "89660", "89700", "89850" } ),
FILTER ( 'Queryx', LEFT ( 'Queryx'[Accnt], 3 ) IN { "899" } )
)
If I run the measure with only 1 filter the measure works, but the addition of the other 2 filters throws a wrench in the system. Any idea how I could get this to run? Or is there a smarter way to go about creating this measure?
Thanks for taking the time to read this and I greatly appreciate any help =)
The filters are all applied using AND logic. I suspect you want to use OR logic since it's not possible to satisfy all those conditions at once.
Try something more like this:
Measure =
CALCULATE (
SUM ( 'Queryx'[Amount] ),
FILTER (
Queryx,
LEFT ( 'Queryx'[Accnt], 4 )
IN { "8980", "8981", "8982", "8983", "8987", "8988", "8989" }
|| [Accnt] IN { "89660", "89700", "89850" } ),
|| LEFT ( 'Queryx'[Accnt], 3 ) IN { "899" } )
)
)
The || is the logical OR syntax.

DAX HASONEVALUE row filter

12 Total :=
SWITCH (
TRUE (),
HASONEVALUE ([level04] ), CALCULATE (
[Local],
DATESINPERIOD (
Calendar[Date],
MAX ( Calendar[Date] ),
-12,
MONTH
)
),
HASONEVALUE ([level03]),If([level 03]= "calculation:" && [level03]= "Cash:" && [level03]= "Costs:"=>0, Blank(), CALCULATE (
[Local],
DATESINPERIOD (
Calendar[Date],
MAX ( Calendar[Date] ),
-12,
MONTH
)
)
),
HASONEVALUE ( [level02] ), BLANK ()
)
I would like to add condition that if lever 03 = cash, calculation, and cost then return blank to remove sub total rows. I tried something like that and its not working properly it gives me error "value for column level03 cannot be determined in the current context". how can i add that condition in level03 column?
Just a side note, "its not working properly" is tremendously unhelpful in determining the source of problems. Specifically in a Power Pivot/Tabular model, this link provides a list of ways to help answerers help you.
Syntactically, there are some errors. Let's address those and see if the behavior is appropriate before diving into alternate measure definitions.
This section is the problem:
...
,HASONEVALUE([level03])
// Note, you are inconsistent in referring to [level03] and
// [level 03]
,If( // Below you are testing column references against scalar
// literals. DAX doesn't understand how to do this, so you
// have to wrap each reference in a VALUES() function, which
// can be implicitly converted to a scalar value
[level 03] = 'calculation:' // DAX needs double quotes: ""
&& [level03]= 'Cash:' // You have multiple predicates
&& [level03]=' Costs:'=>0 // for a single field combined
// with a logical and - these
// can't all simultaneously be true
,Blank()
,CALCULATE(
[Local]
,DATESINPERIOD(
Calendar[Date],
MAX ( Calendar[Date] ),
-12,
MONTH
)
)
)
,....
I am just going to change the combination of predicates to a logical or in my rewrite, so that it's possible for this IF() to return a BLANK. The way it's written above, even fixing the syntax errors will cause it to always evaluate the else condition, because [level 03] cannot simultaneously have the value of "calculation:", "Cash:", and " Costs:=>0".
...
,HASONEVALUE('<table>'[level03])
// As a best practice, you should always use fully qualified
// column references - 'table'[field]
// Also, I've referred only to [level03] below
,IF( // Note we've wrapped [level 03] in VALUES() below - this will
// allow our comparisons to scalar literals
VALUES('<table>'[level03]) = "calculation:" // double quotes
|| VALUES('<table>'[level03]) = "Cash:"
// Note: we've changed the logical and, &&, to a logical
// or, || - meaning if any 1 of these predicates is true,
// we'll return BLANK
|| VALUES('<table>'[level03]) = " Costs:=>0"
,BLANK()
,CALCULATE(
[Local]
,DATESINPERIOD(
Calendar[Date]
,MAX( Calendar[Date] )
,-12
,MONTH
)
)
)
,....
What this will do is check for any cell on the pivot table where [level03] has exactly one distinct value - when this is true, it will evaluate the IF() function.
The IF() function will check the value of [level03]. If that value is any one of the three following values, "calculation:", "Cash:", or " Costs:=>0", it will return BLANK. If the value of [level03] is not any of those three, it will evaluate the CALCULATE(), which returns the measure [Local] for a rolling 12 month period.

Resources