I have started to learn some basic usage in Power BI and need help in solving a problem.
Please see my table attached.
I want to calculate the average of the percentage of the last entry with the last "Status 1" for each ID. In my database there are some ID's in which the Status "Status 1" is just contained once (like ID 4) - I would like to exclude those ID's. Is that possible?
For this example it would be:
(94 + 82 + 85) / 3 = 87
I have started with trying to calculate the average of all "Percent" for all "Status 1".
Test Average 2 =
CALCULATE (
AVERAGEX(Tabelle1; Tabelle1[Percent]);
FILTER ( ALL ( Tabelle1 ); Tabelle1[Status]="Status 1" );
ALL (Tabelle1)
)
How do I proceed? I don't know how to create the code with so many conditions. I have tried to research the solution but gave up. I hope you can help me and would appreciate the help for a Coding beginner :)
Thanks in advance,
Jenny
First, welcome to the Power BI family!
Second, here is how I would approach your problem...
1. Create a "DateTime" column
Since we need to check for the latest entry, and presumably you want that checked based on date and time, it is easier if there is only one column to check).
In the ribbon, go to Modeling -> New Column.
In the formula bar that pops up, enter the following formula. Power BI can recognize the date and time columns for what they are and since they are both elements of date/time, Power BI lets us do simple addition. The - 1 in the formula is to account for the "day" that is associated with the time.
DateTime = [Date] + [Time] - 1
2. Create Average Measure
Here is the whole formula first and following is a breakdown piece by piece.
Last Percent Average =
VAR TargetStatus = "Status 1"
VAR IDsWithMoreThanOneStatus1 = FILTER('Data', COUNTROWS(FILTER('Data', IFERROR(SEARCH(TargetStatus, [Status]), -1) > 0 && [ID] = EARLIER([ID]))) > 1)
VAR LastStatus = FILTER(IDsWithMoreThanOneStatus1, IFERROR(SEARCH(TargetStatus, [Status]), -1) > 0 && [DateTime] >= MAXX(FILTER('Data', IFERROR(SEARCH(TargetStatus, [Status]), -1) > 0 && [ID] = EARLIER([ID])), [DateTime]))
RETURN
DIVIDE(SUMX(LastStatus, [Percent]), COUNTROWS(LastStatus), BLANK())
The first chunk of the measure is defining variables. Variables are super useful and I would encourage you to at least take a quick look at them. Here's just one article on them.
The first variable is simply designating the target status (in case you ever want to change it). This variable is optional as if it will never change, you could just put the text into the other formulas.
VAR TargetStatus = "Status 1"
The second variable filters the master list of data to only those IDs with more than one "Status 1" (excluding ID = 4 in this case). One of the keys with this variable is the EARLIER function. While it is horribly named (in my opinion), it is immensely useful. You can read the official documentation on it here.
Step by step through the variable: We want to filter the Data table... where the row count is greater than one... when we filter the table to include "Status 1" for the specified ID.
The SEARCH function will look at the entire string and tell us the starting position of our search string (TargetStatus). We need to wrap it in an IFERROR function to handle cases where TargetStatus does not show up in the [Status] value. Then we just check to see if the result is greater than 0 indicating that the TargetStatus is in the [Status] value.
VAR IDsWithMoreThanOneStatus1 =
FILTER(
'Data',
COUNTROWS(
FILTER(
'Data',
IFERROR(SEARCH(TargetStatus, [Status]), -1) > 0 &&
[ID] = EARLIER([ID])
)
) > 1
)
The third variable filters the list from the second variable to capture the last "Status 1" for each ID. This uses the same thought process as the second variable: we want to filter the table (from the second variable) where the status = "Status 1" and the [DateTime] is greater than or equal to the max [DateTime] for all "Status 1" for the specified ID.
VAR LastStatus =
FILTER(
IDsWithMoreThanOneStatus1,
IFERROR(SEARCH(TargetStatus, [Status]), -1) > 0 &&
[DateTime] >= MAXX(
FILTER(
'Data',
IFERROR(SEARCH(TargetStatus, [Status]), -1) > 0 &&
[ID] = EARLIER([ID])
),
[DateTime]
)
)
The RETURN keyword is just telling Power BI that we are done defining variables and that everything else in the formula defines the actual value that is returned for this measure.
RETURN
Lastly is the average itself. In this case, we'll use SUMX to sum up all of the [Percent]s from the third variable, and then divide it by the row count of the third variable. I would always recommend using the DIVIDE function as it handles for dividing by 0 and other errors.
DIVIDE(
SUMX(
LastStatus,
[Percent]
),
COUNTROWS(LastStatus),
BLANK()
)
When it's all said and done, your measure will give the desired result.
Related
I have the following structure of tables:
fact_Phone (* < 1) Dim_Users (* <> 1) Dim_user_ID
The fact_Phone table have usernames. This is many to one, single direction to dim_users
The dim_users have the username and proper name but not the ID. This is many to one in both directions to dim_user ID
The dim_user_ID have proper name, user ID and country.
I figured out how to check if the handling times of the calls are on target or not, although I had to separate the handling times into two different measures first, leading to the need of two columns. This is not wanted, and I cannot figure out how to merge them into one measure, while still checking for my country condition from my dim_user_ID table.. any ideas?
In my Matrix, I use dim_user_ID[country] as my rows with the dim_user_ID[name] as the secondary row, and then I tried to use my calculated measures to show the average handling times. So far, so good. ..except that they are in different columns.
This is what I have tried so far, although that means I have to have two measures, ultimately forcing me to have two columns (one for each country, which is not wanted):
AHT (Phone NO) = DIVIDE(
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="NO"
), fact_Phone[Total AHT]
),
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="NO"
), fact_Phone[Total calls answered]
)
)
AHT (Phone SE) = DIVIDE(
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="SE"
), fact_Phone[Total AHT]
),
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="SE"
), fact_Phone[Total calls answered]
)
)
Then based on this one, I create one new measure that can be used for the conditional formatting:
Check AHT on target =
IF(
'1 Measures'[AHT (Phone NO)] > 240
|| '1 Measures'[AHT (Phone SE)] > 260,
0,
1
)
Solved:
Kept the two measures above, and changed the last measure to this:
Check AHT on target =
IF(
NOT(ISBLANK('1 Measures'[AHT (Phone NO)]))
|| NOT(ISBLANK('1 Measures'[AHT (Phone SE)])),
IF(
'1 Measures'[AHT (Phone NO)] > 240
|| '1 Measures'[AHT (Phone SE)] > 260,
0,
1
))
Then it worked to us this measure as the "What field should we base this on?" in the conditional formatting for a simpler AHT measure:
AHT (Phone) = DIVIDE(SUM(fact_Phone[Total AHT]),SUM(fact_Phone[Total calls answered]))
Solved it. I only had to create the to measures AHT (Phone NO) and AHT (Phone SE), then I could use the "Check AHT on target" measure on one simpler measure being ´AHT (Phone) = DIVIDE(SUM(fact_Phone[Total AHT]),SUM(fact_Phone[Total calls answered])) ..now I just need to figure out how to return nothing if the AHT for the specific measures result in blanks.. and I will mark this as the answer later, I have to wait two days though.
I calculate dayd over day. the measure returns correct values, but the total always 0 which is wrong, how to correct it ?
sales day over day = var _maxdate=CALCULATE(max('Date'[Date]), ALLSELECTED('Date'[Date]))
var _mindate=CALCULATE(min('Date'[Date]), ALLSELECTED('Date'[Date]))
var dates=filter(values('Date'[Date]), 'Date'[Date]<=_maxdate && 'Date'[Date]>=_mindate)
return if(ISEMPTY('Date'), BLANK()
, calculate(sum(Sales[Sales]), PREVIOUSDAY('Date'[Date]))+0)
I attach the pbix file https://1drv.ms/u/s!Amd7BXzYs7AVhBBCo_Ls7q5IkrXH?e=1ZQzsE
I'm not familiar with powerBI, but I suppose when column 'Date' is empty, blank() is returned but such value is not an illegible value to calculate 'total'. Try to remove these rows, or assuming an alternative date for that cases
I have a matrix that I am using in Power BI visualization.
Percentage Status
High Low Medium
10% 1
20% 1
30% 1
"1" is the count of values in a column. I want to display 0 where there is no data in the above matrix.
I have tried dong below:
Adding +0 at the end of measure.
= IF(CALCULATE(COUNT(Table[col])=ISBLANK()),0,COUNT(Table[col]))
But, nothing seems to work as it is not considering no data as blank.
I don't think you can do this with just a measure. There are no rows of data in the table that correspond to those empty cells, so it doesn't even try to evaluate a measure.
What you can do is create a calculated table and use that in your Columns field.
Status = VALUES(Table[Status])
Create the relationship from that table to your original table on the Status column and replace Table[Status] with Status[Status] in your matrix visual. Now adding +0 should do the trick.
Measure = COUNT ( Table[col] ) + 0
You are checking the True False condition with ISBLANK(), use directly value as Blank() to compare the cell value,
=
IF (
CALCULATE (
COUNT ( Table[col] )
= BLANK ()
),
0,
COUNT ( Table[col] )
)
Hope it helps!!
Please check it here..
I need to calculate running total of forecast amount starting from maximum value, based on two stock locations and once for each product (product numbers are repetitive due to stock locations). e.g product no "1" should be used once for running total.
My first code, which didn't sum the same forecast amounts independently based on item no.
RunningTotal1 =
VAR
CurrentAmount= Listing[Forecast Amount]
RETURN
SUMX (
FILTER (
Listing;
Listing[Forecast Amount]>= CurrentAmount);
Listing[Forecast Amount])
My second code where running total was based on stock location, it calculates for each location independently still didn't sum the same forecast amounts independently based on item no.
RunningTotal2 =
VAR CurrentAmount = Listing[Forecast Amount]
VAR Location = Listing[Stock Location]
RETURN
SUMX (
FILTER (
Listing;
Listing[Stock Location] = Location &&
Listing[Forecast Amount]>= CurrentAmount);
Listing[Forecast Amount])
But when I add second location to my formula it gives an error.
"DAX comparison operations do not support comparing values of type Text with values of type True/False. Consider using the VALUE or FORMAT function to convert one of the values."
RunningTotal3 =
VAR CurrentAmount = Listing[Forecast Amount]
VAR LocationW = Listing[Stock Location] = "Warehouse"
VAR LocationT = Listing[Stock Location] = "Total Stock"
RETURN
SUMX (
FILTER (
Listing;
Listing[Stock Location] = LocationW ||
Listing[Stock Location] = LocationT &&
Listing[Forecast Amount]>= CurrentAmount);
Listing[Forecast Amount])
What I expect is
Hello #RADO,
I tried to add as measure but couldn't succeed therefore I added as a new column. I realize my code is wrong, in your image item no 5 and 6 have different number. my formula is
Forecast Index = RANKX(Listing;Listing[Forecast Amount])
here's the result Forecast Index
regards
You need to add a column to your "Listing" table that defines order for the running total. You can't use Forecast Amount for that, because there are cases where different items have the same amounts (for example, items 66 and 99), and there is no way to resolve these ties (which items should be accumulated first - 66 or 99? No way to tell).
Often, date/time fields are used for that, but if you don't have them, you can add an index based on whatever rules you need. For this example, I manually added "Forecast Index" as follows:
Forecast index here is simply a sorting order - if you sort by it, you will get the layout exactly matching your "desired result" table.
Then, create a measure:
RT Expected =
VAR Current_Index = MAX ( Listing[Forecast Index] )
VAR Summary_Table =
SUMMARIZE (
FILTER (
ALL ( Listing ),
Listing[Forecast Index] <= Current_Index &&
Listing[Stock Location] <> "Without Stock" ),
Listing[Item No],
Listing[Forecast Amount] )
RETURN
SUMX ( Summary_Table, Listing[Forecast Amount] )
Result:
Note: If you don't want to see Items 2 and 4, simply remove them from the visual filter.
How it works:
First, we use FILTER to create a virtual table that a) ignores "Without Stock" locations, and b) keeps only forecast amounts that we need for the running total;
Second, we use SUMMARIZE to group that virtual table by Item No and Forecast Amount. The grouping eliminates duplicates;
Finally, we use SUMX to iterate the de-duplicated table, and sum up all relevant amounts.
Edit:
You can create a proper index using PowerQuery:
In your left panal, Go to "Data", and select "Listing" table;
Right-click the table, and select "Edit Query". Power BI will take you to the Power Query window;
In Power Query, first, sort column "Forecast Amount" Descending. Then, sort column "Item No" Ascending. This will arrange your records in the same order as you have them in your picture;
Finally, in Power Query window, go to "Add Column", then "Index Column", select "From 1". Power Query will create an index column for you, and name it "Index". You can rename it as needed (i.e, to "Forecast Index");
Click "Close and Apply", and then build the measure I suggested using this new index column as an input.
In case these instructions are not clear, refer to this article:
https://www.excelguru.ca/blog/2018/06/14/ranking-method-choices-in-power-query/
I've been struggling with DAX while creating a model to publish on Power BI and the actual problem is presented on the image here. Basically I need a column that shows the value from the predecessor time for the same id.
I did with ranking but wanted to know if it is possible to make it better.
How would you guys do it?
Rank = COUNTROWS(FILTER(test; [id] = EARLIER([id]) && [Date] <= EARLIER([Date])))
Past = if(test[Rank]=1;0; LOOKUPVALUE(test[qt];teste[Rank];test[Rank]-1;test[id];test[id]))
This is a solution tested with the basic model you posted, I don't guarantee this is a machine low cost expression but you can give it a try.
I've created a column called PREVIOUS in which is calculated the previous qty for every row based on the date for the same id.
PREVIOUS =
CALCULATE (
MAX ( TableName[qt] ),
FILTER (
TableName,
EARLIER ( TableName[id] ) = TableName[id]
&& EARLIER ( TableName[date] ) > TableName[date]
)
)
The following is a Power BI table using the PREVIOUS column.
Let me know if this helps.