A tabular model.
The table 'Historic Project One Hour Value' contains hours value (like price) for working hours on projects on several dates.
It is connected only to the project table but not to the date table .
I'm trying to calculate the hours value. For my question let's say there is only one hour on each project.
I get the correct answer for each project, but the total is a very big number, which I don't understand.
I will appreciate your help.
One Hour Value On Date :=
VAR OneHourValueOnStartDate =
FILTER (
'Historic Project One Hour Value',
'Historic Project One Hour Value'[HistoricOneHourValueBeginDate]
= DATE ( 2016, 12, 31 )
)
VAR OneHourValueOnStartDateForOneProject =
1
* /*Actually, I multiply the working hours of the project, but this number is correct */
CALCULATE (
SUM ( 'Historic Project One Hour Value'[HistoricOneHourValue] ),
OneHourValueOnStartDate
)
RETURN
IF (
HASONEVALUE ( Projects[Project ID] ),
CALCULATE ( OneHourValueOnStartDateForOneProject ),
CALCULATE (
SUMX ( VALUES ( Hours[HoursProjectID] ), OneHourValueOnStartDateForOneProject )
)
)
The variable OneHourValueOnStartDateForOneProject is a constant (not a measure), so what's happening in your total is that this value gives you the sum for all Project ID values in the VAR calculation part.
From there, your SUMX adds that constant value the same number of times as there are distinct HoursProjectID.
The correct code after Alexis Olson answer:
One Hour Value On Date:=
VAR OneHourValueOnStartDate =
FILTER (
'Historic Project One Hour Value',
'Historic Project One Hour Value'[HistoricOneHourValueBeginDate]
= date(2016,12,31)
)
VAR OneHourValueOnStartDateForOneProject =
1 * /*Actually, I multiply the working hours of the project, but this number is correct */
CALCULATE (
SUM( 'Historic Project One Hour Value'[HistoricOneHourValue] ),
OneHourValueOnStartDate
)
RETURN
IF (
HASONEVALUE ( Projects[Project ID] ),
CALCULATE ( OneHourValueOnStartDateForOneProject ),
CALCULATE (
SUMX (
Values ( Hours[HoursProjectID] ),
1
* CALCULATE (
MAX ( 'Historic Project One Hour Value'[HistoricOneHourValue] ),
FILTER (
OneHourValueOnStartDate,
'Historic Project One Hour Value'[HistoricOneHourValueProjectID]
= EARLIER ( 'Hours'[HoursProjectID] )
)
)
)
)
)
Thank you
Related
1/ How to calculate the number of sales days (= number of days at least one sale has been done)?
So far, I created this measure, but I'd like to know if another more optimal solution exists for a large sales table (1b+ records):
Sales[No of Sales Days] :=
CALCULATE (
DISTINCTCOUNT ( Sales[Date Key] )
)
2/ How to calculate number of sales days in the current year? Is anything more optimal than this?
Sales[No of Sales Days YTD] :=
CALCULATE (
[No of Sales Days],
DATESYTD ( 'Calendar'[Calendar Date] )
)
It really depends on your model. There are a few options which have been written about.
https://gorilla.bi/dax/optimize-distinctcount/
https://www.sqlbi.com/articles/analyzing-distinctcount-performance-in-dax/
I would try a few different options e.g.:
Sales[No of Sales Days] =
COUNTROWS(
SUMMARIZE(
‘Sales’
,’Sales[Date Key]
)
)
Yes, There is a better code as DISTINCTCOUNT is a problematic structure in DAX. Please try this, and confirm the results back to me!
Q1)
Sales[No of Sales Days] :=
CALCULATE ( SUMX ( VALUES ( Sales[Date Key] ), 1 ) )
Q2)
Sales[No of Sales Days YTD] :=
VAR CurrentYear =
YEAR ( TODAY () )
RETURN
CALCULATE (
[No of Sales Days],
FILTER ( ALL ( Calendar[Year] ), Calendar[Year] = CurrentYear )
)
I have a Power BI visual as below. There are 3 matrices. I have a DateDimension (or) Calendar table called Dates2.
I use two measures, one a regular measure (called 'Count'), the other a parallel period comparison of the measure (called 'Count_PreviousYear'). I use SAMEPERIODLASTYEAR DAX function for the latter.
1)
Count = COUNTA(TableX[ColumnY])
--Measure with name 'Count'--
2)
Count_PreviousYear = CALCULATE
(
[Count],
SAMEPERIODLASTYEAR(Dates2[Date])
)
--Measure with name 'Count_PreviousYear'
--this measure uses Time Intelligence function - SAMEPERIODLASTYEAR--
Both 'Count' and 'Count_PreviousYear' (obviously) are not YTD (YearToDate) values.
A third measure for the percentage change across periods is computed as below:
3)
PercentageChange = IF(
ISBLANK([Count]) || ISBLANK([Count_PreviousYear]),
BLANK(),
(([Count] - [Count_PreviousYear])/[Count])
)
Kindly ignore the fact that a keyword used as a measure name;
I have used the name 'Count' only for clarity; in my actual report,
I have proper names
The % change measure works fine, but one issue:
For the period change from 2020 to 2021, i.e. in the third row of the last matrix (for the row value 2021), the total (i.e. the % change value) is not appropriate.
I need to replace -737.21% with - 23.98 %.
This is because , I need to compute the Total for 2020, only by adding the values for the months of January and February, i.e. 428 + 430 = 858. (not 5794, which is for all the 12 months).
Since 2021 has only two months - January and February, I don't want to compare two months of 2021, with all the 12 months of 2020. Rather, I want two months of 2021 to be compared with the corresponding 2 months of 2020.
Essentially I need {(692-858)/692} * 100 = -23.98%
Currently, I see {(692-5794)/692} * 100 = -737.21%
Can someone help me achieve this?
Count Previous Year =
IF (
HASONEVALUE ( Dates2[Month] ),
IF (
[Count] <> BLANK (),
CALCULATE ( [Count], SAMEPERIODLASTYEAR ( Dates2[Date] ) )
),
IF (
HASONEVALUE ( Dates2[Year] ),
CALCULATE (
[Count],
DATESBETWEEN (
Dates2[Date],
EDATE ( MIN ( Dates2[Date] ), -12 ),
EOMONTH ( MAX ( [FactTable[Date] ), -12 )
)
)
)
)
Count_PreviousYear = IF (
(HASONEVALUE(Dates2[Year]) = TRUE && HASONEVALUE(Dates2[MonthName]) = TRUE),
CALCULATE
(
[Count],
SAMEPERIODLASTYEAR(Dates2[Date])
),
IF (
(HASONEVALUE(Dates2[Year]) = TRUE && HASONEVALUE(Dates2[MonthName]) = FALSE),
CALCULATE (
[Count],
DATESBETWEEN (
Dates2[Date],
EDATE (MIN(Dates2[Date]), -12),
EOMONTH (MAX(SourceData[Date]), -12)
)
),
BLANK()
)
)
!Output obtained as desired]1
I have this dataset and calculated Datediff1 using below calculated column. Issue is no execution take place between 12am to 5am but when i calculate duration it adds extra 5 hours which is not giving exact duration, Any help will be appreciated.
Datediff1 =
ABS(
DATEDIFF (
CALCULATE (
MIN ( OTC[End Date] ),
FILTER (
OTC,
OTC[Index] = EARLIER ( OTC[Index] )+1
)
),
OTC[End Date],
MINUTE
)
)
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.