DAX conditional sum - powerbi

How to construct a DAX measure which returns sum of either A or B. The logic is take B if A is empty. So expected results looks like this:
+---+---+----------+
| A | B | Expected |
+---+---+----------+
| 1 | | 1 |
| 1 | | 1 |
| | 2 | 2 |
| 1 | 2 | 1 |
| | 2 | 2 |
+---+---+----------+
| 3 | 6 | 7 |
+---+---+----------+
When I use measure:
Measure = IF(ISBLANK([SUM(tab[A])]), SUM(tab[B]), SUM(tab[A]))
I get 3 for total which is logical but not what I expect.

I'd recommend using a SUMX iterator in this case.
Measure = SUMX ( tab, IF ( ISBLANK ( tab[A] ), tab[B], tab[A] ) )
You might be able to do the following as well:
Measure =
CALCULATE ( SUM ( tab[A] ) ) +
CALCULATE ( SUM ( tab[B] ),
FILTER ( tab, ISBLANK( tab[A] ) )
)

Related

Get latest value for each ID in Power BI / DAX measure

In Power BI I would like to create a DAX measure that will retrieve the latest string value for specific IDs. Example source table:
Name_ID | Name | DateTime | Value
----------------------------------------------------------
1 | Child_1 | 18.8.2021 12:33:24 | F
32 | Parent_32 | 18.8.2021 11:41:09 | F
13 | Child_1 | 18.8.2021 11:30:58 | E
48 | Parent_48 | 18.8.2021 09:13:11 | F
2 | Child_2 | 17.8.2021 00:09:42 | S
1 | Child_1 | 17.8.2021 23:03:34 | F
48 | Parent_48 | 17.8.2021 21:46:27 | S
6 | Parent_6 | 16.8.2021 17:31:26 | S
.
.
.
specific parents IDs for example here are 6, 32 and 48, so the result should be something like this:
Name_ID | Name | DateTime (of last execution) | Value
------------------------------------------------------------------------------
32 | Parent_32 | 18.8.2021 11:41:09 | F
48 | Parent_48 | 18.8.2021 09:13:11 | F
6 | Parent_6 | 16.8.2021 17:31:26 | S
The result table I'm trying to get is only parents latest appearance and retrieving the whole row or just Value from last column.
This seems so easy in theory and on paper but I just can't seem to get it in DAX I have tried with various calculate formulas but without any result worth mentioning .
I'm beginner in Power Bi and any help would be very appreciated!
You can use a measure like this one, where we check Max Date per Name:
Flag =
var MaxDatePerName = CALCULATE(max(Sheet3[DateTime]), FILTER(ALL(Sheet3), SELECTEDVALUE(Sheet3[Name]) = Sheet3[Name]))
return
if( MaxDatePerName = SELECTEDVALUE(Sheet3[DateTime]) && LEFT(SELECTEDVALUE(Sheet3[Name]),6) = "Parent", 1, BLANK())
With RANKX
Measure2 =
VAR _0 =
MAX ( 'Table 1'[DateTime] )
VAR _00 =
MAX ( 'Table 1'[Name] )
VAR _1 =
CALCULATE (
RANKX (
FILTER ( ALL ( 'Table 1' ), 'Table 1'[Name] = _00 ),
CALCULATE ( MAX ( 'Table 1'[DateTime] ) ),
,
DESC
)
)
VAR _2 =
IF ( _1 = 1 && CONTAINSSTRING ( _00, "Parent" ) = TRUE (), _0, BLANK () )
RETURN
_2

Select row with MAX value per category Power BI/DAX

How to select the row with a max value per category in DAX/SSAS? Suppose we have table:
+----------+-------+------------+
| Category | Value | Date |
+----------+-------+------------+
| apples | 1 | 2018-07-01 |
| apples | 2 | 2018-07-02 |
| apples | 3 | 2018-07-03 |
| bananas | 7 | 2018-07-04 |
| bananas | 8 | 2018-07-05 |
| bananas | 9 | 2018-07-06 |
+----------+-------+------------+
Desired results are:
+----------+-------+------------+
| Category | Value | Date |
+----------+-------+------------+
| apples | 3 | 2018-07-03 |
| bananas | 9 | 2018-07-06 |
+----------+-------+------------+
From your question it is not clear whether you want to return a table or a measure.
If you need to return a table, then go with this:
calculated_table
:=VAR _categoryfirst=
ADDCOLUMNS (
VALUES ( 'Table'[Category] ),
"MinValue", CALCULATE (MIN ( 'Table'[Value] ),ALL ( 'Table'[Value] ))
)
RETURN
CALCULATETABLE(
SELECTCOLUMNS('Table',
"Category", 'Table'[Category]
"Value", 'Table'[Value]
"Date", 'Table'[Date]
),
KEEPFILTERS (
TREATAS (
_categoryfirst,
'Table'[Category],
'Table'[Value]
)
)
)
Instead, if you want to create a Table visualization with Category, Value, Date showing only the row associated with minimum value I would go with this:
measure:=
VAR _categoryfirst=
CALCULATETABLE(
ADDCOLUMNS (
VALUES ( 'Table'[Category] ),
"MinValue", CALCULATE (MIN ( 'Table'[Value] ),ALL ( 'Table'[Value] ))
),
ALL('Table'[Value]),
ALL('Table'[Date])
)
RETURN
CALCULATE(
MIN('Table'[Value]),
KEEPFILTERS (
TREATAS (
_categoryfirst,
'Table1'[Category],
'Table1'[Value]
)
)
)

DAX Median of category sums

How to calculate median of category sums? I have sample data:
+----------------+-----------+
| category | sales |
+----------------+-----------+
| a | 1 |
| a | 2 |
| a | 4 |
| b | 1 |
| b | 3 |
| b | 4 |
| c | 1 |
| c | 4 |
| c | 5 |
+----------------+-----------+
+----------------+-----------+
| category | sales_sum |
+----------------+-----------+
| a | 7 |
| b | 8 | <- This median
| c | 10 |
+----------------+-----------+
| median of sums | 8 | <- This is expected results, regardless row context
+----------------+-----------+
I have had little success with this measure. It returns correct results but only for category total. But I want to get 8 for each category.
Median_of_sums :=
MEDIANX (
VALUES ( T[Category] ),
SUM ( T[Sales] )
)
I am not entirely sure what you are looking for, but perhaps using the SUMMARIZE function would do the trick here:
Total =
MEDIANX (
SUMMARIZE (
T,
T[category],
"Sales_Calc", SUM ( T[sales] )
),
[Sales_Calc]
)
The idea is to first summarize the information at a category level initially and then calculating the median for the summarized table. This would give the following results for the attached sample:
a 7
b 8
c 10
Total 8
If you want 8 to be reflected for all categories, you would have to use the ALL function to make sure the category context does not affect the calculation:
Total =
MEDIANX (
SUMMARIZE (
ALL ( T ),
T[category],
"Sales_Calc", SUM ( T[sales] )
),
[Sales_Calc]
)
Hope this helps.

DAX Measure to calculate aggregate data, but group by Case ID

So I have a variable
var varSubItem = CALCULATE (MAX(Outages[SubItem]), Outages[DATE] >= DATE(2019, 07, 14) )
to calculate out items that have had an outage within 1 day. See below.
Then I have another variable
var data =
CALCULATE (
COUNT ( Outages[CASE_ID] ),
ALLSELECTED ( Outages ),
Outages[SubItem] = devices
)
which gives me back the outage count for the devices in the last 2 years. It's only the last two years because my table visual has a filter for that time frame.
I pray that I'm making sense because I have been trying to do this for 2 weeks now.
Devices w Outages 2Yr =
VAR devices =
CALCULATE ( MAX ( Outages[DEVICE_ID] ), Outages[DATE] >= DATE ( 2019, 07, 14 ) )
VAR data =
CALCULATE (
COUNT ( Outages[CASE_ID] ),
ALLSELECTED ( Outages ),
Outages[DEVICE_ID] = devices
)
RETURN data
I'm getting this,
| Area | Item | SubItem | Case | Date | Outage Count |
|--------|------|---------|-----------|-----------------|--------------|
| XXXXX' | ABC1 | 123A | 123456789 | 7/14/19 1:15 AM | 1 |
| | ABC2 | 123B | 132456798 | 7/14/19 3:20 AM | 1 |
| | ABC3 | 123C | 984561325 | 7/14/19 6:09 PM | 1 |
| | ABC4 | 123D | 789613453 | 7/14/19 3:54 PM | 3 |
| | ABC5 | 123E | 335978456 | 7/14/19 2:10 PM | 2 |
| Total | | | | | 8 |
When I should be getting this,
| Area | Item | SubItem | Case | Date | Outage Count |
|--------|------|---------|-----------|-----------------|--------------|
| XXXXX' | ABC1 | 123A | 123456789 | 7/14/19 1:15 AM | 1 |
| | ABC2 | 123B | 132456798 | 7/14/19 3:20 AM | 1 |
| | ABC3 | 123C | 984561325 | 7/14/19 6:09 PM | 1 |
| | ABC4 | 123D | 789613453 | 7/14/19 3:54 PM | 1 |
| | ABC4 | 123D | 789613211 | 4/19/18 4:20 AM | 1 |
| | ABC4 | 123D | 789611121 | 9/24/17 5:51 AM | 1 |
| | ABC5 | 123E | 335978456 | 7/14/19 2:10 PM | 1 |
| | ABC5 | 123E | 335978111 | 2/21/19 7:19 AM | 1 |
| Total | | | | | 8 |
I think what you want is closer to this:
Devices w Outages 2Yr =
VAR devices =
CALCULATETABLE (
VALUES ( Outages[SubItem] ),
ALLSELECTED ( Outages ),
Outages[DATE] >= TODAY() - 1
)
RETURN
CALCULATE (
COUNT ( Outages[Case] ),
FILTER ( Outages, Outages[SubItem] IN devices )
)
This creates a list of SubItem values rather than the single one you get with MAX and that's where your ALLSELECTED function needs to go.
Edit: To total at the SubItem level try this tweak:
Devices w Outages 2Yr =
VAR devices =
CALCULATETABLE (
VALUES ( Outages[SubItem] ),
ALLSELECTED ( Outages ),
Outages[DATE] >= TODAY() - 1,
VALUES ( Outages[SubItem] )
)
RETURN
CALCULATE (
COUNT ( Outages[Case] ),
ALLSELECTED ( Outages ),
Outages[SubItem] IN devices
)
The exact logic here is a bit complex for a beginner DAX user, but just keep in mind that DAX is all about filters.
For the variable devices, we want a list of all SubItem values in the current context subject to a date constraint. The CALCULATETABLE function allows us to modify our filter context. The ALLSELECTED function is a table filter removes any filter context from the visual so that all Date and Case values that aren't filtered out by slicers or page/report level filters are included. Otherwise, you'd get blanks for rows that have dates before TODAY()-1. The date value boolean filtering is self-explanatory, but then I add another table filter at the end, VALUES(Outages[SubItem]), to add back the SubItem context from the visual.
The CALCULATE piece functions similarly. We count all the Case values after altering the filter context to remove filter context on Case and Date and only taking SubItem values from the list generated in the variable.

How to calculate an expression and group by 2 fields in DAX?

I want to write an expression in DAX that will group by 2 fields: AgentID and LoginDate. Here is the expression:
Average Availability % Per Day = (LoginTime + WorkTime) / (LoginTime + WorkTime + BreakTime)
What I have written in DAX so far is :
Average Availability % Per Day =
AVERAGEX (
VALUES ( Logins[LoginDay] ),
(
DIVIDE (
SUM ( Logins[LoginDuration] ) + SUM ( Logins[WorkDuration] ),
SUM ( Logins[LoginDuration] ) + SUM ( Logins[WorkDuration] )
+ SUM ( Logins[BreakDuration] )
)
)
)
However, the problem is the expression is summing everything and then getting the average as opposed to evaluating the expression and grouping by each day and each AgentID before calculating the average.
EDIT: Adding sample data:
AgentID | LoginDay | LoginDuration | BreakDuration | WorkDuration
96385 | 7/5/2018 | 14472 | 803 |1447
96385 | 7/6/2018 | 14742 | 857 |1257
96385 | 7/12/2018 | 14404 | 583 |291
96385 | 7/13/2018 | 14276 | 636 |368
96385 | 7/19/2018 | 14456 | 788 |543
96385 | 7/20/2018 | 14550 | 390 |1727
96385 | 7/26/2018 | 66670 | 53224 |1076
96385 | 7/27/2018 | 14592 | 277 |1928
So for example, for this agent, I am getting an average availability % per day of .75 when it should really be .91