Just wondering about best practices, and SPEED in asking this:
Does it matter if You Create a measure on a measure that is based on another measure,
or is it better to base that new Measure on the base Measure?
eg
BaseMeasure= Sum(x)
Measure1= Calculate(BaseMeasure,y=1 || y=2)
Should Measure2 be
(a) Calculate(Measure1, y=2)
OR
(b) Calculate(BaseMeasure,y=2)
this is not valid DAX, but let's assume it's some pseudo-code
The main problem is that a and b measures would return different results
The (a) measure sets a filter context to y = 2, but then the Measure1 replaces this filter context with y = 1 || y = 2, and then evaluate the BaseMeasure with this filter. The result is precisely the same as if Measure1 was directly invoked.
The (b) measure instead sets the filter context to y = 2 and then invokes the BaseMeasure with this filter.
This can be simulated on dax.do with the following DAX code
DEFINE
TABLE T =
DATATABLE ( "Y", INTEGER, "X", INTEGER, { { 1, 10 }, { 2, 20 } } )
MEASURE T[BaseMeasure] =
SUM ( T[X] )
MEASURE T[Measure1] =
CALCULATE ( [BaseMeasure], T[Y] = 1 || T[Y] = 2 )
MEASURE T[Measure2] =
CALCULATE ( [Measure1], T[Y] = 2 )
MEASURE T[Measure3] =
CALCULATE ( [BaseMeasure], T[Y] = 2 )
EVALUATE
ROW ( "Measure2", [Measure2], "Measure3", [Measure3] )
that returns
here is the link to the dax.do example
To answer the question about nesting measure call, when done correctly it's ok, but focusing mainly on the code architecture and readability.
From the performance point of view, it's hard to predict the performance just by looking ad the code (unless really bad), the right path for optimization is through testing.
Related
I am new with Dax. I have a matrix table in Power BI which has been imported from Excel. I need to create a dynamic DAX measure which will give me the values if both conditions are filtered.
This is a very big table and the measure has to be dynamic as values keep changing.
For eg:
Criteria : A, B, C
Code : 101,102,103
Values: 94, 50, 63
If Criteria is A and Code is 101 then value = 94
If Criteria is B and Code is 102 then value = 50
If you need measure based on columns that you put in your matrix on rows or columns, you may use this.
YourMeasure = IF( MAX( Tab[fruit] ) = "Apple" & MAX( Tab[size] ) = "Big", 1, 0 )
Probably what you are after, and what is safer, is adding new calculated column in your source table:
CalculatedColumn =
IF(
Tab[friut] = "Apple" // condition 1
& // AND opperator
Tab[size] = "Big", // condition 2
1, // result if true
0 // result if false
)
Where 1 is returned if both conditions are met.
If your condition path is complex you might use SWITCH function.
SWITCH( TRUE(),
Tab[column1] = "Apple" & Tab[column2]="Big", "Big Fruit",
Tab[column1] = "Carot" & Tab[column2]="Small", "Small Vegetable",
"Other thing"
)
I need some help with my measure counting correct in total.
This is the MainTable:
With my Measure "CountPass" I count every ID distinct with the action "pass":
CountPass = CALCULATE(DISTINCTCOUNT(Workflow[ID]),Workflow[action]="pass")
Furthermore with my Measure CountPassPreweek I do same with reference on previous Week by using the a date table:
CountPassPreweek =
var currentweek = SELECTEDVALUE(DateTable[WeekNum])
var currentweekday = SELECTEDVALUE(DateTable[WeekNo])
var currentyear = SELECTEDVALUE(DateTable[Year])
var maxweeknum = CALCULATE(MAX(DateTable[WeekNum]),all(DateTable))
Return
SUMX(
if(currentweek = 1,
DateTable[WeekNo] = currentweekday && DateTable[WeekNum] = maxweeknum && DateTable[Year] = currentyear - 1,
DateTable[WeekNo] = currentweekday && DateTable[WeekNum] = currentweek -1 && DateTable[Year] = currentyear)),
[CountPass]
)
This is working so far but not showing the totals, so I have a second measure for doing that:
CountPreweekTotal =
var _table = SUMMARIZE(DateTable,DateTable[Date],"_value",[CountPassPreweek])
return
SUMX(_table,[_value])
And here you see my problem: The measure doesn't count distinct like the "original" counting Measure as you see here
Hope somebody can help me with that.
Thanks a lot!
It's counting 3 since abc is getting counted twice the way your measure is written (since dates are separated in your SUMMARIZE).
Since you appear to have a proper date table, you should be able to use time intelligence functions to write this much more simply as
CountPassPreviousWeek =
CALCULATE ( [CountPass], DATEADD ( DateTable[Date], -7, DAY ) )
This should work for the total too.
can someone please check if my theoretical understanding of variables is correct?
Suppose that I have a table with 2 columns, Condition1 and Condition2.
I want to count the rows for which Condition1 = 4, and Condition2 = Black.
Soppose then that I write a measure called Black, that creates a Table where all rows have Condition2 = "Black". For Example:
Black:= FILTER (Table, Condition2 = "Black")
And then I write the combined code using variables:
Black4_version1 =
var B = [Black]
return = CALCULATE(
COUNTROWS(B),
Condition1 = 4)
Then this code will not work because DAX thinks that the variable B is a single number (because it's calling a measure and measure is by default seen as a single value?), even though I have created a measure that should have created a table.
But if I create the table within a variable itself, then DAX will know that it's a table and then it will work?
Black4_Version2 =
var B = FILTER (Table, Condition2 = "Black")
return = CALCULATE(
COUNTROWS(B),
Condition1 = 4)
I'm asking this because I want to be 100% sure that I have understood the answer given here: DAX: please explain why this measure with a variable will not work
also because I have been using variables already at work, so I will need to re-check all the dashboards that I have built and talk to my manager about screwing up a big time. So you could say that my job depends on this.
Variables are to be considered constants even when they contain a table. In your Black4_Version2 measure, the CALCULATE() doesn't change the COUNTROWS(B) result, since it's counting the rows of a constant table and no filtering is happening.
Black4_Version2 =
VAR B =
FILTER(
Table,
Condition2 = "Black"
)
RETURN
CALCULATE(
COUNTROWS( B ),
Condition1 = 4
)
but you can iterate over a constant table, therefore FILTER works
Black4_Version3 =
VAR B =
FILTER(
Table,
Condition2 = "Black"
)
RETURN
COUNTROWS(
FILTER(
B,
Condition1 = 4
)
)
P.S. I used the pseudo-DAX sintax used in the answer, since instead of Condition1 = 4 a column reference like Table[Column1] = 4 should be used
Hi guys, I am new to Power BI(DAX formulas) and I am attempting to calculate the percentage contribution of the sum of "count" where "category" = X and "item_no"=1 to the total of "count" across all categories where 'item_no' = 1.
The ideal mathematical statement here will be the (30/50)*100%
I intend to represent the percentage values in a chart showing percentage contribution of each distinct item_no to its total in the format as represented in the example above.
The standard way to approach this is
calculation over partial set / same calculation over larger set
Since you haven't made it clear what context you are trying to calculate this, I will assume it's a visual along these lines:
The measure I use here is
%ItemTotal =
DIVIDE (
SUM ( Table1[count] ),
CALCULATE ( SUM ( Table1[count] ), ALLEXCEPT( Table1, Table1[item_no] ) )
)
In the numerator, you have the sum in the local filter context. For example, in that top-left cell, this means all rows that match item_no = 1 and category = "X".
In the denominator, we do the same thing except we remove all filter context except the context we say to keep (item_no) so it includes all category values.
If you're trying to calculate that 60% outside of the context of a visual, then you can explicitly define what filters you want. For example, this should work in any filter context:
X%_Item1 =
DIVIDE (
CALCULATE (
SUM ( Table1[count] ),
ALL ( Table1 ),
Table1[category] = "X",
Table1[item_no] = 1
),
CALCULATE (
SUM ( Table1[count] ),
ALL ( Table1 ),
Table1[item_no] = 1
)
)
See here and here for other ways to modify the filter context instead of ALLEXCEPT.
I'm trying to create a trending table with a value and a forecast. The forecast needs to start from the current month going forward. I am using this dax function:
Spend Forecast =
IF (
OR (
DIVIDE (
CALCULATE (
SUM ( refv_Spend_Cap[Spend_2019] ),
FILTER ( refv_Spend_Cap, refv_Spend_Cap[Split] = "Spend Actual" )
),
1000000
)
< 1,
DIVIDE (
CALCULATE (
SUM ( refv_Spend_Cap[Spend_2019] ),
FILTER ( refv_Spend_Cap, refv_Spend_Cap[Ind_Monthend] = "x" )
),
1000000
)
< 1
),
DIVIDE (
CALCULATE (
SUM ( refv_Spend_Cap[Spend_2019] ),
FILTER ( refv_Spend_Cap, refv_Spend_Cap[Split] = "Spend Forecast" )
),
1000000
),
""
)
The formula is calculating to check if these two conditions are met:
if there's no value then populate the forecast or if the ind monthend = 'x' then it should populate, if those two conditions are not met then it should leave it blank.
There are no syntax errors on the query but i am getting this error:
The True/False expression does not specify a column. Each True/False
expressions used as a table filter expression must refer to exactly
one column
Where did I go wrong?
It's very hard to comprehend such long formulas. It's the best practice to break them down into multiple measures. For example, your code can be re-writen as follows:
Create base measure:
Total Spend = SUM ( refv_Spend_Cap[Spend_2019] ) / 1000000
Now re-use the base measure to create 3 conditional measures. No need to use FILTER here:
Spend Actual = CALCULATE ( [Total Spend], refv_Spend_Cap[Split] = "Spend Actual" )
Spend X = CALCULATE ( [Total Spend], refv_Spend_Cap[Ind_Monthend] = "x" )
Spend Forecast = CALCULATE ( [Total Spend], refv_Spend_Cap[Split] = "Spend Forecast" )
Then the final result is simply:
Forecast = IF ( [Spend Actual] < 1 || [Spend X] < 1, [Spend Forecast], "")
It's much easire to understand what's happening, and easier to debug. You will also gain perfomance bonus because (usually) re-used measures are cached and calculated only once.
Try this code, if it still gives you problems, describe the new error and I'll help you fix it.
BTW, there is a popular free tool to format your DAX code:
Dax Formatter