I have a Power BI report that calculates the number of jobs due in a month and reports on how many jobs are completed on time. The report works well except the measure totals do not add up correctly like the table columns do.
I have measures in place for:
Done on time = Jobs completed in their due month
Outside time = Jobs completed after when they were due.
Incomplete = Used to identify incomplete jobs
% Perf = Percentage of jobs completed on time."
Other fields:
DUE = Due Date
completed = job completion date
I have found a possible answer to this using (HASONEFILTER) but cannot get it to work.
MEASURES
Done on time =
VAR DueMonth = MONTH ( FIRSTDATE ( Table1[due_date] ) )
RETURN
CALCULATE (
[Due],
FILTER ( Table1,
MONTH ( Table1[completed] ) = DueMonth || MONTH (
Table1[completed] ) = DueMonth -1 || MONTH ( Table1[completed] ) = DueMonth +1
)
)
Outside time =
VAR DueMonth = MONTH ( FIRSTDATE ( Table1[due_date] ) )
RETURN
CALCULATE (
[Due] - [Done on time],
FILTER (
Table1,
MONTH ( Table1[completed] ) <> DueMonth || MONTH ( Table1[completed] ) = DueMonth -1 || MONTH ( Table1[completed] ) = DueMonth +1 ||
NOT ISBLANK ( Table1[completed] )
)
)
% Perf =
DIVIDE (
[Done on time],
[Due],
BLANK()
) * 100
Results would be properly totaled column measure's, screenshot below of existing output.
Related
I have the following table, imported in Power BI - QOL_Exp (see screenshot example below)
I need to create a calculated table which will filter out values, where Rating = 999 and,
at the same time, will pick only the highest and the lowest Date values from Date column, based on ClientID (see highlighted grey and peach colored areas).
I highlighted in red font - the values that I expect to see in my calculated table
For example, for ClientID = 3052 I will need the records where Date = 11/20/2020 (lowest date for this ClientID) and Date = 5/17/2021 (highest date for this ClientID)
For ClientID = 2666 I will not need the record where Rating = 999 (one of the conditions)
I managed to filter out (to exclude Rating = 999) but struggling with including only Max and MIN date in the new calculated table
This is my DAX:
QOL = CALCULATETABLE(QOL_Exp, QOL_Exp[Rating]<>999)
How should I modify it in order to only leave Max(Date) and Min(Date) records, based on ClientID?
UPD:
Based on the answer given, slightly updated (see below):
QOL =
FILTER (QOL_Exp, QOL_Exp[Rating] <> 999
&&
(( QOL_Exp[Date] = CALCULATE (MIN ( QOL_Exp[Date] ),
ALLEXCEPT(QOL_Exp,QOL_Exp[ClientID])))
|| QOL_Exp[Date] = CALCULATE (MAX ( QOL_Exp[Date] ),
ALLEXCEPT(QOL_Exp, QOL_Exp[ClientID]))))
QOL =
FILTER (
QOL_Exp,
QOL_Exp[Rating] <> 999
&& (
QOL_Exp[Date]
= CALCULATE (
MIN ( QOL_Exp[Date] ),
FILTER (
QOL_Exp,
QOL_Exp[Rating] <> 999
&& QOL_Exp[ClientID] = EARLIER ( QOL_Exp[ClientID] )
)
)
|| QOL_Exp[Date]
= CALCULATE (
MAX ( QOL_Exp[Date] ),
FILTER (
QOL_Exp,
QOL_Exp[Rating] <> 999
&& QOL_Exp[ClientID] = EARLIER ( QOL_Exp[ClientID] )
)
)
)
)
How to adjust the below solution source
to show census year (CY) which starts 16th of April and ends 15th of April?
(i.e.: for dates between '2020-04-16' AND '2021-04-15': 'CY2020-21', for dates between '2019-04-16' AND '2020-04-15': 'CY2019-20, and so on).
Financial Year =
VAR fy =
IF (
MONTH ( 'Dates'[Dates] ) <= 3,
VALUE ( FORMAT ( 'Dates'[Dates], "YY" ) ) - 1,
VALUE ( FORMAT ( 'Dates'[Dates], "YY" ) )
)
RETURN
CONCATENATE ( "FY", CONCATENATE ( fy, CONCATENATE ( "/", fy + 1 ) ) )
You can do this a bit more cleanly as follows:
CY =
VAR yr = FORMAT ( STARTOFYEAR ( 'Dates'[Date], "4/15" ), "YY" )
RETURN
"CY" & yr & "-" & yr + 1
Note: For this to work properly for the earliest year, the Dates table should start at the beginning of the census year.
I am stuck in the situation where I am adding a new calculated column but it's prompting me the circular dependency. The first column is calculated like:
=VAR Denominator = ( Validation_Accounts_Agreements[CalculatedClosedDateVsFirstPurchaseDate] + 1 )
VAR Sales =
CALCULATE (
SUM ( SalesR48NBVBySolution[TotalSales] ),
FILTER (
SalesR48NBVBySolution,
SalesR48NBVBySolution[invoicedate] >= Validation_Accounts_Agreements[CalculatedFirstAnchorPurchaseDateAfterGTWClosedDate]
)
)
VAR R6AnchorSales =
CALCULATE (
SUM ( SalesR48NBVBySolution[TotalSales] ),
FILTER (
SalesR48NBVBySolution,
SalesR48NBVBySolution[invoicedate]
>= EDATE (
Validation_Accounts_Agreements[CalculatedFirstAnchorPurchaseDateAfterGTWClosedDate],
-6
)
&& SalesR48NBVBySolution[invoicedate] < Validation_Accounts_Agreements[CalculatedFirstAnchorPurchaseDateAfterGTWClosedDate]
&& SalesR48NBVBySolution[ClensedAnchorDesignation] = "Y"
)
)
RETURN
IF ( ISBLANK ( R6AnchorSales ),
IF ( NOT (ISBLANK ( Validation_Accounts_Agreements[CalculatedFirstAnchorPurchaseDateAfterGTWClosedDate] )
)
&& ISBLANK ( R6AnchorSales ),
DIVIDE ( Sales, Denominator ) * 12
)
)
The next column I want to create here is:
=VAR Denominator = ( Validation_Accounts_Agreements[CalculatedClosedDateVsFirstPurchaseDate_SLN] + 1 )
VAR Sales =
CALCULATE (
SUM ( SalesR48NBVBySolution[TotalSales] ),
FILTER (
SalesR48NBVBySolution,
SalesR48NBVBySolution[invoicedate] >= Validation_Accounts_Agreements[CalculatedFirstPurchasedateAfterGTWClosedDate_SLN]
)
)
VAR R6AnchorSales =
CALCULATE (
SUM ( SalesR48NBVBySolution[TotalSales] ),
FILTER (
SalesR48NBVBySolution,
SalesR48NBVBySolution[invoicedate]
>= EDATE (
Validation_Accounts_Agreements[CalculatedFirstPurchasedateAfterGTWClosedDate_SLN],
-6
)
&& SalesR48NBVBySolution[invoicedate] < Validation_Accounts_Agreements[CalculatedFirstPurchasedateAfterGTWClosedDate_SLN]
&& SalesR48NBVBySolution[ClensedAnchorDesignation] = "N" && CALCULATE(MAX('CAM Alignment'[NodeCd_L3])=="C3-10-00015")
)
)
RETURN
IF ( ISBLANK ( R6AnchorSales ),
IF ( NOT (ISBLANK ( Validation_Accounts_Agreements[CalculatedFirstPurchasedateAfterGTWClosedDate_SLN] )
)
&& ISBLANK ( R6AnchorSales ),
DIVIDE ( Sales, Denominator ) * 12
)
)
Here is more info about my model::
In the above picture, the yellow highlighted columns I am using to create the calculated column 1 (calculated Annualization).The red circled columns are being used to create column 2 ( calculated Annualization_SLN).both sets of columns are almost similar (changes in the filter).But when I am trying to create column 2 ( calculated Annualization_SLN) that time I am getting this error of circular dependency; which is dependent on column 1.
In general, according to best-practice avoid extensively using Calculated Columns. Instead, add them in your data source (back-end) or use M-Query.
In order to answer your question precisely, you need to share more information about your model (i.e. relationships). However, we can provide you some guidelines referring to this article in order to avoid circular dependencies.
Quoting the conclusion of the article:
Most of the time, circular dependencies occur when you use calculated tables. You can easily avoid them by paying attention to your choice of functions. The difference between DISTINCT and VALUES, or between ALL and ALLNOBLANKROW is a subtle difference. But once you get used to it, your code will be safer when it comes to relationships and circular references.
I'm working on some calculations for capital budgeting, and I have the following two tables in my data model
I'm trying to build out a calculated column in DAX to determine the payback period for each project in the Project table. I've put together the calculation here, I'm just not sure exactly how to execute this in DAX.
Logical Steps for Calculating Payback Period:
For each Project, find the cumulative sum for each date for relevant metrics (Include OpEx Savings and OpEx Implementation Cost, but not Revenue or Working Capital)
Find the MIN date where cumulative sum is greater than zero (the "break-even" date")
Find the MIN date with non-zero implementation cost ("Investment date")
Find the difference (in months) between #2 and #3 to determine payback period
EDIT:
The answer for the listed project is 7 months. I've built an intermediate table in Excel to develop the answer, but I'd like to be able to do this directly in a PowerPivot table with DAX.
I've produced this as a solution:
Create values, which makes sure cost are - and savings are + (ValCorr)
Create a running sum (RunningSum)
Find Investment Date (InvestmentDate)
Find Breakeven Date (BreakEvenDate)
Find Difference (Payback)
DAX:
RunningSum =
CALCULATE(SUM(Impacts[ValCorr]);
FILTER(
ALL(Impacts);
Impacts[ProjectID] = EARLIER(Impacts[ProjectID]) &&
Impacts[Date] <= EARLIER(Impacts[Date])
))
InvestmentDate =
CALCULATE (
FIRSTNONBLANK ( Impacts[Date]; 0 );
FILTER ( ALL ( Impacts ); Impacts[RunningSum] <> 0 )
)
BreakEvenDate =
CALCULATE (
FIRSTNONBLANK ( Impacts[Date]; 0 );
FILTER ( ALL ( Impacts ); Impacts[RunningSum] > 0 )
)
Payback = DATEDIFF(Impacts[InvestmentDate];Impacts[BreakEvenDate];MONTH)
Result:
Good luck!
After a fair amount of trial and error, I came up with a solution.
Step 1: Build out a helper metrics table. This serves 2 purposes: (a) excludes irrelevant metrics (like revenue), and (b) ensure costs are negative and savings are positive.
Metrics Table
Step 2: Build 2 helper measures that will go into the virtual, summarized, intermediate table.
CumulativeTotalMetric :=
CALCULATE (
SUMX (
Impact,
Impact[Latest Estimate Monthly Values]
* RELATED ( BaseMetrics[Payback Period Multiplier] )
),
FILTER ( ALL ( Impact[Month] ), Impact[Month] <= MAX ( Impact[Month] ) )
)
TotalMetric :=
SUMX (
Impact,
Impact[Latest Estimate Monthly Values]
* RELATED ( BaseMetrics[Payback Period Multiplier] )
)
Step 3: Create the final measure that creates the virtual table (BaseTable), and performs logical operations on it to arrive at the final payback period.
Payback Period (Years) :=
VAR BaseTable =
ADDCOLUMNS (
SUMMARIZE ( Impact, Impact[initiative #], Impact[snapshot], Impact[Month] ),
"Cumulative Total Impact", CALCULATE ( [CumulativeTotalMetric] ),
"Total Impact", CALCULATE ( [TotalMetric] )
)
VAR LastCumulativeLossDate =
MAXX ( FILTER ( BaseTable, [Cumulative Total Impact] < 0 ), [Month] )
VAR BreakEvenDate =
MINX (
FILTER (
BaseTable,
[Month] > LastCumulativeLossDate
&& [Cumulative Total Impact] > 0
),
[Month]
)
VAR InitialInvestmentDate =
MINX ( FILTER ( BaseTable, [Total Impact] < 0 ), [Month] )
RETURN
IF (
OR ( ISBLANK ( InitialInvestmentDate ), ISBLANK ( BreakEvenDate ) ),
BLANK (),
( BreakEvenDate - InitialInvestmentDate )
/ 365
)
This last meaure is pretty complicated. It uses progressive, dependent variables. It starts with the same base table, and defines variables that are used in subsequent variables. I'm no DAX expert, but I suspect using these variables helps with the calculation efficiency.
EDIT: I should note that I didn't use this measure as a calculated column -- I simply used it in a pivot table which is the same "shape" as the "Projects" table above -- one line per project / initiative.
I have two measures in my tabular cube.
The first one called
'Number of Days' := CALCULATE(COUNTROWS(SUMMARIZE('A'[Date])))
The second one will includes the first one as its expression
'Number of Days (MTD)' := CALCULATE(TOTALMTD([Number of Days],'A'[Date]))
The second measure when I browse the cube and pull out the measure.
It runs incredibly slow.
Any idea how I can optimize these measurements and make it run faster?
Sample Data
Volume:= SUMX(A, DIVIDE([Volume],2))
Volume (MTD):= TOTALMTD([Volume],'A'[Date])
Updated extra measurements
The best practice should be creating a Calendar/Date table and use TOTALMTD Time Intelligence function. However this approach can be used if your model doesn't include a Date table.
First measure, number of days:
Num of Days := DISTINCTCOUNT(A[Date])
Cumulative measure:
Num of days (MTD) :=
CALCULATE (
[Num of Days],
FILTER (
ALL ( A ),
[Date] <= MAX ( A[Date] )
&& MONTH ( [Date] ) = MONTH ( MAX ( [Date] ) )
&& YEAR ( [Date] ) = YEAR ( MAX ( [Date] ) )
)
)
UPDATE: Added screenshot.
UPDATE 2: It seems you need to calculate a cumulative total, in that case just use the below expression for the second measure:
Num of days (MTD) :=
CALCULATE ( [Num of Days], FILTER ( ALL ( A ), [Date] <= MAX ( A[Date] ) ) )
UPDATE 3: Usuing SUMX and DISTINCT to count distinct dates.
Replace the first measure by the following:
Num of Days = SUMX(DISTINCT(A[Date]), 1)
This solution could be more performant than use COUNTROWS + SUMMARIZE,
however it could be very slow depending on the number of rows and the
machine where it is running.
Let me know if this helps.