SSAS Calculation & MDX - expression

I cannot figure out how to turn this SSAS Calculation expression into a MDX query so I can evaluate the parts of the calculation. Please help!
The calculation is applied to a cube with dimensions: Year, Month, Store, Department, and Account. It also has 1 measure named Amount.
The calculation expression is as follows:
(
([Accounts].[All Levels].[Level 1].&[Gross Profit].&[Dept1],[Measures].[Amount])+
([Accounts].[All Levels].[Level 1].&[Gross Profit].&[Dept2],[Measures].[Amount])
)
/
(
([Accounts].[All Levels].[Level 1].&[Labor],[Measures].[Amount])+
([Accounts].[All Levels].[Level 1].&[Expenses],[Measures].[Amount])
)
It's basically trying to take the Gross Profits for Departments 1 & 2 only, and then divide it by the total of the Labor and Expenses (all departments).
This will be done for the year, month, and store selected (or in total).
Now, what I want to do is see what is making up the final results I'm seeing by the different dimensions in the cube so I can validate the calculation.
For example, let's say the resulting amount is 40% if I select Year: 2018, Month: Jan: Store: L001.
What I'd like to see what the amounts were for Gross Profit (for Dept1 and Dept2) versus the amounts for Labor and Expenses. Meaning the actual underlying amounts, but in detail
I've tried just placing in the calculation expression:
select
(
([Accounts].[All Levels].[Level 1].&[Gross Profit].&[Dept1],[Measures].[Amount])+
([Accounts].[All Levels].[Level 1].&[Gross Profit].&[Dept2],[Measures].[Amount])
)
/
(
([Accounts].[All Levels].[Level 1].&[Labor],[Measures].[Amount])+
([Accounts].[All Levels].[Level 1].&[Expenses],[Measures].[Amount])
)
FROM
My Cube
;
And got the error: "Parser: The statement dialect could not be resolved due to ambiguity."

Try this:
WITH MEMBER [Measures].[Gross Profit] as
(
([Accounts].[All Levels].[Level 1].&[Gross Profit].&[Dept1],[Measures].[Amount])+
([Accounts].[All Levels].[Level 1].&[Gross Profit].&[Dept2],[Measures].[Amount])
)
/
(
([Accounts].[All Levels].[Level 1].&[Labor],[Measures].[Amount])+
([Accounts].[All Levels].[Level 1].&[Expenses],[Measures].[Amount])
)
SELECT [Measures].[Gross Profit] on COLUMNS
FROM
My Cube
;

Related

Microsoft Power BI - DAX Time Intelligence measure - change context to reflect proper % change; non-YTD measures

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

Filter Dax Calculation based upon YTD Sum

In a Tabular SSAS Model, I'm trying to count the number of distinct customers that purchased a given product wtihin a YTD Timeframe. The table contains measures that aren't explicit sums, so I get the Cartesian Product of all products for each customer, regardless of no sales. I'm attempting to limit the count by filtering out customer / product combinations with YTD Sales = 0. However, I cannot get the FILTER to recognize the DATESYTD context. It only ever filters based upon Sales existing within the chosen calendar month. I've tried inserting the ALL function every which way.
This is what I have so far.
Measure:
CALCULATE (
DISTINCTCOUNT ( Fact[Customer] ),
DATESYTD ( Calendar[Date] ),
FILTER ( Fact,
CALCULATE ( [Sum of Sales], DATESYTD ( Calendar[Date] ) ) <> 0
)
)
This measure will, for example, count distinct customers purchasing a product in Month #5 if Month #5 is explicitly chosen. It will not, however, include a customer that purchased that item in Month #2 of the same year.
I think the following DAX should do the trick:
COUNTROWS(
FILTER(
VALUES(Fact[Customer]),
CALCULATE ( [Sum of Sales], DATESYTD ( Calendar[Date] ) ) <> 0
)
)
Also, make sure your 'Calendar' table has been marked as a date table. If, for some reason, you prefer not to mark it as a date table, rewrite the above DAX to:
COUNTROWS(
FILTER(
VALUES(Fact[Customer]),
CALCULATE ( [Sum of Sales], DATESYTD ( Calendar[Date] ), ALL('Calendar') ) <> 0
)
)
Edit: Do you have records in your fact table where [Sum of Sales] is 0? If not, then you could simplify and improve the performance considerably by writing:
CALCULATE(
DISTINCTCOUNT(Fact[Customer]),
DATESYTD( Calendar[Date] )
)
Again, if you haven't marked your 'Calendar' table as a date table, add ALL(Calendar) to remove the filter on specific calendar columns.

Calculating payback period using DAX

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.

Condition with multiple columns in DAX

can I somehow filter in DAX with multiple columns?
I need filter that the difference between two dates are lower than 300 days like below.
EVALUATE
(
CALCULATETABLE
(
SUMMARIZE
(
'Sales',
'Sales'[MaxDatum],
'Sales'[MinDatum]
),
INT('Sales'[MaxDatum] - 'Sales'[MinDatum]) < 300
)
)
So it failed with this error:
The expression contains multiple columns, but only a single column can
be used in a True/False expression that is used as a table filter
expression.
I tried another construction of that query like this, but in this case I cannot reuse the calculated member.
EVALUATE
(
CALCULATETABLE
(
SUMMARIZE
(
'Sales',
'Sales'[MaxDatum],
'Sales'[MinDatum],
"DIFF", INT('Sales'[MinDatum] - 'Sales'[MaxDatum])
),
[DIFF] < 300
)
)
Is possible to do this somehow in DAX query?
Thanks for your help
Try this:
EVALUATE
(
FILTER (
ADDCOLUMNS ( Sales, "Diff", 1 * ( Sales[MaxDatum] - Sales[MinDatum] ) ),
[Diff] < 300
)
)
If you are using SSAS 2016, Excel 2016 or Power BI you can use the DATEDIFF function which is a more reliable way to calculate time deltas.
Let me know if this helps.

DAX Year over Year

I have been trying to get this DAX expression to show me cumulative searches for last financial year. Here is an example of the information;
Fiscal Week Fiscal Year Searches Brand
1 14 1000 Example1
1 15 1200 Example1
2 14 1000 Example1
2 15 1200 Example2
My formula below is working a little, but when I apply an slicers to the data it breaks in PowerBI. i.e. if I slice by another field, like brand.
Cum. Searches PY =
IF (
HASONEVALUE ( 'data'[Fiscal Year] ),
CALCULATE (
SUM ( 'data'[Searches] ),
FILTER (
ALL( 'data' ),
'data'[Fiscal Year.] = VALUES ( 'data'[Fiscal Year] ) - 1
&& CONTAINS(
VALUES ( 'data'[Fiscal Week] ),
'data'[Fiscal Week],
'data'[Fiscal Week] )
)
),
BLANK ()
)
I'd appreciate any pointers to where I'm going wrong? Thanks in advance.
I think it can be simplified, I dont understand the need for the HASONEVALUE or CONTAINS functions. I would use something like the following for your measure:
Cum. Searches PY:= CALCULATE(
SUM( Table1[Searches] ),
FILTER(
ALL( Table1[Fiscal Year] ) ,
Table1[Fiscal Year] = MAX( Table1[Fiscal Year] ) - 1
)
)
With that sample data above, this will produce results of:
Example1 2000
Example2 (Blank)
If that's not your expected result, then explain exactly what you want.

Resources