Power BI Complex Calculated Column - powerbi

I'm quite new to Power BI and I try to query Azure DevOps data for a Board with historical data.
I have made an OData feed that queries data and returns the data below (see table) and for each row where IsCurrent = True, I want to calculate the "blocked time" into a new Column BlockedTime for that WorkItemId. So I need to traverse records for that WorkItemId and do date calculation.
I am kind of stuck currently after much delving into CALCULATE, Filters and more.
I have specified three scenarios for the WorkItemId 1, 72 and 149.
I use the column Index as the number to reference lines in my calculations below.
My query returns the following:
WorkItemId Revision Index AnalyticsUpdatedDate IsCurrent TagNames BlockedTime
72 7 0 06/19/2020 11.41.04 True See calculation 1
72 6 1 06/19/2020 11.41.04 False Blocked
72 5 2 06/18/2020 10.41.23 False Blocked
72 4 3 06/17/2020 09.38.54 False
72 3 4 06/16/2020 14.22.21 False Blocked
72 2 5 06/15/2020 15.01.02 False
72 1 6 06/14/2020 07.21.16 False
1 6 7 07/07/2020 09:58:12 True Blocked See calculation 2
1 5 8 07/07/2020 09:58:12 False
1 4 9 07/06/2020 10:22:02 False Blocked
1 3 10 07/05/2020 12:34:31 False
1 2 11 07/04/2020 13:51:30 False Blocked
1 1 12 07/03/2020 08:23:41 False
149 1 13 07/02/2020 10:01:55 False Blocked See calculation 3
RULES
Variable CurrentDate contains current DateTime
When TagNames contains "Blocked" text for a given line it is considered blocked from the date/time in AnalyticsUpdatedDate and the time should be calculated "backwards" by traversing down in the records (Revision number going down) and summarized until a line without "Blocked" in TagNames is encountered
Calculation 1: Calculate BLOCKED TIME and put the result into BlockedTime(0)
(AnalyticsUpdatedDate(1) - AnalyticsUpdatedDate(2)) +
(AnalyticsUpdatedDate(2) - AnalyticsUpdatedDate(3)) +
(AnalyticsUpdatedDate(4) - AnalyticsUpdatedDate(5))
Calculation 2: Calculate BLOCKED TIME and put the result into BlockedTime(7)
(CurrentDate - AnalyticsUpdatedDate(7)) +
(AnalyticsUpdatedDate(9) - AnalyticsUpdatedDate(10)) +
(AnalyticsUpdatedDate(11) - AnalyticsUpdatedDate(12))
Calculation 3: Calculate BLOCKED TIME and put the result into BlockedTime(13)
(CurrentDate - AnalyticsUpdatedDate(13))
Anyone who has any ideas of how this could be solved best?

So here we go. I made it in 3 steps with 3 columns so it is a bit easier to follow, you can make it in one script.
First we need to find the dates of all teh releases (when the block is not there anymore)
This we do with the following column:
Released =
var workItemId = Track[WorkItemId]
var Revision = Track[Revision]
var ReleaseTime = CALCULATE(MIN(Track[AnalyticsUpdatedDate]), FILTER(Track, Track[WorkItemId] = workItemId && Revision < Track[Revision]))
var ReleaseFinal = if (ISBLANK(ReleaseTime), NOW(), ReleaseTime)
return if(Track[TagNames] = "Blocked", ReleaseFinal)
In the calculate, I am getting the first row (MIN) where the item ensuring I have the same workItemId with a release higher.
If I do not find a releaseTime, it means the item is still blocked so I populate the ReleaseFinal with NOW().
As I only want output when the item is blocked, I have an if on the last return
Next I create a new column to calculate the difference in seconds:
SecDiff = DATEDIFF(Track[AnalyticsUpdatedDate],Track[Released], SECOND)
The last column I created to sum the seconds together and poplulate the column with the IsCurrent = True:
TotalBlockedTime =
var WorkItemId = Track[WorkItemId]
return if (Track[IsCurrent], CALCULATE(SUM(Track[SecDiff]), FILTER(Track, Track[WorkItemId] = WorkItemId)))
End result, see below. I think your data is not 100% because your 3rd example Iscurrent = false (what should be true).
Enjoy!

Related

DAX Calcuate rolling sum

I have a problem with calculating measure that sums values for 3 previous periods.
Below I attach sample fact table and dict table to show problem I am facing.
date
customer
segment
value
01.01.2021
1
A
10
02.01.2021
1
A
10
03.01.2021
1
A
10
04.01.2021
1
A
10
01.01.2021
2
B
20
02.01.2021
2
B
30
03.01.2021
2
B
40
dict table:
segment
segment_desc
A
Name of A
B
Name of B
Approach I have taken:
last 3 value =
VAR DATES = DATESINPERIOD(facts[date],LASTDATE(facts[date]), -3,MONTH)
RETURN CALCULATE([sum value], DATES)
It produces correct results as long as there is at least one record for April.
When I use filter on segment_desc = 'B'
It produces result as I attached - so we see result in April equals 20, which is obviously not what I wanted. I would expect it to be 50.
Answer to the main question:
time intelligence functions like DATESINPERIOD require a proper calendar table, because they expect continuous dates, without gaps.
Answer to the follow-up question "why the measure shows value for January?"
It's a bit tricky. First, notice that LASTDATE in this filter context returns blank:
So, your DAX measure then becomes this:
last 3 value =
VAR DATES = DATESINPERIOD(facts[date], BLANK(), -3,MONTH)
RETURN CALCULATE([sum value], DATES)
Blank - 3 month does not make sense, so the way DAX resolves this: it replaces BLANK with the first (min) date in the table. In this case, it's 1/1/2021. Then it goes back 3 months from that date. As a result, the final measure is:
last 3 value =
CALCULATE([sum value], {2020-11-01, 2020-12-01, 2021-01-01 })
Since you have no data prior to 2021-01-01, the final result shows only January values.

Calculate cumulative % based on sum of next row

I want to calculate % based on below formula. Its little bit tricks and I am kind of stuck and not sure how to do it. Thanks if anyone can help.
I have few records in below table which are grouped by Range
Range Count
0-10 50
10-20 12
20-30 9
30-40 0
40-50 0
50-60 1
60-70 4
70-80 45
80-90 16
90-100 7
Other 1
I want to have one more column which has the cumulative % based on sum of next row against total row count (145), something like below
Range Count Cumulative % of Range
0-10 50 34.5% (which is 50/145)
10-20 12 42.7% (which is 62/145)
20-30 9 48.9% (which is 71/145)
30-40 0 48.9% (which is 71/145)
40-50 0 48.9% (which is 71/145)
50-60 1 49.6% (which is 72/145)
60-70 4 52.4% (which is 76/145)
70-80 45 83.4% (which is 121/145)
80-90 16 94.5% (which is 137/145)
90-100 7 99.3% (which is 144/145)
Other 1 100.0% (which is 145/145)
Follow the below steps to get your answer. Please vote and accept the answer, If you find the solution helpful.
1st step - - Create an index column from your range column. I have replaced "Other" Value to 999. You can replace it to much bigger number, which is unlikely to be there in your dataset. Convert this new column into whole number
Sort Column = if(Sickness[Range] = "Other",9999,CONVERT(LEFT(Sickness[Range],SEARCH("-",Sickness[Range],1,LEN(Sickness[Range])+1)-1),INTEGER))
2nd Step - Use the below measure to get value:
Measure =
var RunningTotal = CALCULATE(SUM(Sickness[Count]),FILTER(all(Sickness),Sickness[Sort Column] <= MAX(Sickness[Sort Column])))
var totalSum = CALCULATE(SUM(Sickness[Count]),ALL())
Return
RunningTotal/totalSum
Below is the output that exactly matches your requirement.
For cumulative calculation, a ordering is always required. Anyway, if your given values in column "Range" is real - this will also work for this purpose as an ascending ordering on this filed keep data in expected order. Do this following to get your desired output.
Create the following measure-
count_percentage =
VAR total_of_count =
CALCULATE(
SUM(your_table_name[Count]),
ALL(your_table_name)
)
VAR cumulative_count =
CALCULATE(
SUM(your_table_name[Count]),
FILTER(
ALL(your_table_name),
your_table_name[Range] <= MIN(your_table_name[Range])
)
)
RETURN cumulative_count/total_of_count
Here is the final output-

DAX selecting and displaying the max value of all selected records

Problem
I'm trying to calculate and display the maximum value of all selected rows alongside their actual values in a table in Power BI. When I try to do this with the measure MaxSelectedSales = MAXX(ALLSELECTED(FactSales), FactSales[Value]), the maximum value ends up being repeated, like this:
If I add additional dimensions to the output, even more rows appear.
What I want to see is just the selected rows in the fact table, without the blank values. (i.e., only four rows would be displayed for SaleId 1 through 4).
Does anyone know how I can achieve my goal with the data model shown below?
Details
I've configured the following model.
The DimMarket and DimSubMarket tables have two rows each, you can see their names above. The FactSales table looks like this:
SaleId
MarketId
SubMarketId
Value
IsCurrent
1
1
1
100
true
2
2
1
50
true
3
1
2
60
true
4
2
2
140
true
5
1
1
30
false
6
2
2
20
false
7
1
1
90
false
8
2
2
200
false
In the table output, I've filtered FactSales to only include rows where IsCurrent = true by setting a visual level filter.
Your max value (the measure) is a scalar value (a single value only). If you put a scalar value in a table with the other records, the value just get repeated. In general mixing scalar values and records (tables) does not really bring any benefit.
Measures like yours can be better displayed in a KPI or Multi KPI visual (normally with the year, that you get the max value per year).
If you just want to display the max value of selected rows (for example a filter in your table), use this measure:
Max Value = MAX(FactSales[Value])
This way all filter which are applied are considered in the measures calculation.
Here is a sample:
I've found a solution to my problem, but I'm slightly concerned with query performance. Although, on my current dataset, things seem to perform fairly well.
MaxSelectedSales =
MAXX(
FILTER(
SELECTCOLUMNS(
ALLSELECTED(FactSales),
"id", FactSales[SaleId],
"max", MAXX(ALLSELECTED(FactSales), FactSales[Value])
),
[id] = MAX(FactSales[SaleId])
),
[max]
)
If I understand this correctly, for every row in the output, this measure will calculate the maximum value across all selected FactSales rows, set it to a column named max and then filter the table so that only the current FactSales[SaleId] is selected. The performance hit comes from the fact that MAX needs to be executed for every row in the output and a full table scan would be done when that occurs.
Posted on behalf of the question asker

Power BI Measure Calculate %

I please need assistance to calculate % based on the below table.
Table 1 (Fixed Table - Total vehicles per branch)
Table 2 (Distinct Count - Total vehicles based on vehicle regsitation) Current Measure Calculation shown below.
Table 3 (Percentage of Table 2 / Table 1, using Branch Table as Unique Identifier)
Branch 1 = 5
Branch 2 = 5
Branch 3 = 10
Branch 4 = 7
Count Loads = DISTINCTCOUNT('DEL-MAN-REP'[Registration Number])
Vehicles 1 = 5
Vehicles 2 = 3
Vehicles 3 = 1
Vehicles 4 = 4
Branch 1 % = 100%
Branch 2 % = 60%
Branch 3 % = 10%
Branch 4 % = 57%
Any assistance will be appreciated.
If you are in the Data section of Power BI(matrix looking icon on the right task bar), there is a button in the 'Modeling' menu called 'New Column'. Click that and it will create a column named "Column" with the formula set to "Column = ". If you change the "column" in the formula it will change the column name.
Now, start typing the column name you want to use that has the 'Vehicles' data and divide that with the 'Branch' data. finally, press the '%' button under Formatting in the Modeling tab.
If for whatever reason any Branch does not have any vehicles(0), you will need an error handler. so it would look like IFERROR(Vehicles/Branch,0)

PowerBi Change Card values to previous month Value if Current month value is not available

I am working on powerbi, using data over 2 months period, writing dax queries and trying to build reports.
I am trying to show the monthly values in cards visuals.
And i am able to do it using the measure below.
Sample Data:-
PlanPrevMon = CALCULATE([PlanSum],PREVIOUSMONTH('Month Year'[Date]))
CustomKPI = IF(ISBLANK([PlanSum]),"No Data Available ",[PlanSum])&" "&IF([PlanSum]=[PlanPrevMon],"",IF([PlanSum] > [PlanPrevMon],UNICHAR(8679),UNICHAR(8681))&IF([PlanSum]<=0,"",""))
But here i don't want user to choose the month values from slicer.
I would like to show the card values as
if current month value is not available then it should compare with the previous month value automatically as shown in an image below
For example, Apr-2017 value is not available; in this scenario I would like it to compare with the Mar-2017 value.
If Mar-2017 value also not available, then the previous month value and so on
Edit
I tried what #user5226582 suggested but still getting wrong values as below image.
As you can see i restricted to crosscheck whether the value is getting in a right way of not.
But not.
This is the measure i have used as #user5226582 suggested.
c =
var temp = 'Revenue Report'[Date]
return CALCULATE(LASTNONBLANK('Revenue Report'[Planned Rev],
'Revenue Report'[Planned Rev]),
ALL('Revenue Report'),
'Revenue Report'[Date]<=temp)`
Can you please correct me if i am doing anything wrong
Does this help...?
To get the PlanPrevMon column to show like this, I first created a new index column:
id = COUNTROWS(FILTER(Sheet1, EARLIER(Sheet1[Date],1)>Sheet1[Date]))
Then I used the index to help create the PlanPrevMon column in two steps:
Step 1: I made one column named PlanPrevMon1.
PlanPrevMon1 = SUMX(FILTER(Sheet1,Sheet1[id]=EARLIER(Sheet1[id])-1),Sheet1[PlanSum])
Step 2: I made another column named PlanPrevMon.
PlanPrevMon = if(ISBLANK(Sheet1[PlanPrevMon1]),
if(Sheet1[id]=1,0,CALCULATE(LASTNONBLANK(Sheet1[PlanPrevMon1],Sheet1[PlanPrevMon1]),ALL(Sheet1),ISBLANK(Sheet1[PlanSum]))),
Sheet1[PlanPrevMon1])
For the card, I used this measure:
Card = CALCULATE(LASTNONBLANK(Sheet1[PlanPrevMon],1),FILTER(Sheet1,Sheet1[id]=max(Sheet1[id])))
I hope this helps.
You can use LASTNONBLANK DAX function.
Example data:
a b
1 1
2
3 2
4
5 3
Calculated column:
c =
var temp = Table1[a]
return CALCULATE(LASTNONBLANK(Table1[b],Table1[b]),ALL(Table1),Table1[a]<=temp)
Results in:
a b c
1 1 1
2 1
3 2 2
4 2
5 3 3