I'm trying to create an SSAS calculated measure off of an inventory cube. The underlying data contains an inventory_date, a product code, and some inventory values for the product for that date. I am trying to create a measure which will return the first inventory value for the month, for the product (and overall). I've seen people try to use the head function to no avail. I've also just seen a reference to the openingperiod function, which seems to be exactly what I want, but it also isn't returning the correct value. Both of them, FWIW, are returning the last value in the month rather than the first.
Here is a query that I am issuing:
select
[Measures].[Qty On Hand EOD] on 0,
{openingperiod([Inventory Date].[Calendar].[Month]):
[Inventory Date].[Calendar].[Month].&[2018-06-25T00:00:00]
} on 1
from [Daily Inventory]
This query returns for May 2018 the value of [Qty On Hand EOD] for May 31, rather than May 1, which is what I want. What am I doing wrong?
FWIW, in the cube definition the AggregateFunction property for [Qty On Hand EOD] is set to LastNonEmpty (as opposed to Sum or Avg). Could that play a role?
Related
I'm working on Power BI with a live connection SSAS cube. I have two dimension tables, Customer and Year and a fact table. I want to generate a report which shows the proportion of sales amount by citizenship for each Year. I used this MDX expression on SSAS Cube to create a new calculated member.
(([Year].[Year].currentmember,[Dim Customer].[Cittzenship].currentmember),[Measures].[Totale Sales]) /([Cittzenship].currentmember.parent,[Measures].[Totale Sales])
The result of the query works as expected but on power BI report table the total value is infinity.
Result
I'm stuck solving this problem. I would love if somebody guide me how to solve this.
The reason is probably that for the totals, the parent does not exist, and hence, its value is replaced by null for the calculation. In most contexts, SSAS replaces null by 0, and hence the division is by 0, which mathematically is infinity. What you can do is use the Divide function instead of /, which is exactly meant for this purpose, as it delivers the same result as /, except if the divisor is zero, in which case it delivers null.
By the way: Divide was introduced in SSAS 2012, so if you are not on that version at least, you would have to use a construct like IIf(divisor <> 0, dividend / divisor, null), which is exactly how Divide(dividend, divisor) is defined. Like I said
above, in MDX in contrast to SQL, comparing to 0 also implicitly compares to null.
Would much appreciate any help on this.
I have a measure called "Sales" populated with values, however i am trying to turn the "Sales" value to 0, whenever the "Sales Flag" is set to 0.
Important Note: The Sales Flag is based on Date (lowest level of detail).
The difficulty that i am really experiencing and cant get a grip on, is how i am trying the display the MDX outcome.
As explained above, i would want to make the "Sales" value 0 whenever we have a 0 in the "Sales Flag" (which is based on the Date), but when I run the MDX Script I would wan't on the ROWS to NOT display the Date, but instead just the Week (higher Level to Date), as below shows:
I really have spent hours on this and can't seem to understand how we can create this needed custom Sales measure based on the Sales Flag on the date level, but having the MDX outcome display ROWS on Week level.
Laz
You need to define the member in the MDX before the select. Something like that:
WITH MEMBER [Measures].[Fixed Sales] as IIF([Sales Flag].currentMember=1,[Sales], 0)
SELECT [Measures].[Fixed Sales] on 0, [Sales Flag] on 1 from [Cube]
I am writing the code without SSAS here so it might not be the 100% correct syntax but you can get the general idea ;)
You can add the iif in the SELECT part but I find creating member to be the cleaner solution.
SELECT IIF([Sales Flag].currentMember=1,[Sales], 0) on 0, [Sales Flag] on 1 from [Cube]
If you have a control over the cube in SSAS you can create a calculated member there and you can access it easier.
Glad to hear if Veselin's answer works for you, but if not...
Several approaches are also possible.
Use Measure expression for Sales measure:
Use SCOPE command for Day level (if it's Key level of Date dimension). If it's not a key level you have to aggregate on EVERY level (week, year etc) to emulate AggregateFunction of Sales measure but with updated behavior for one flag:
SCOPE([Date].[Your Date Hierarchy].[Day].members,[Measures].[Sales]);
THIS=IIF([Sales Flag].CurrentMember = 1,[Measures].[Sales],0);
END SCOPE;
Update logic in DSV to multiply Sales column by SalesFlag. This is the easiest way from T-SQL perspective.
I'm trying to add a calculated member to my cube, which will return the first fiscal year where there is any data at all in a particular measure.
The purpose is to suppress (i.e. NULLify) various year-on-year calculated measures when the year is this first year: in that year, comparison with the previous year is meaningless.
I've got this so far:
WITH MEMBER Measures.DataStartYear_Sales
AS
HEAD(
NONEMPTY([Calendar].[Fiscal Periods].[Fiscal Year].Members,[Measures].[QuantityOrdered])
,1).Item(0).Properties("NAME")
At the moment:
a. It's a query-scoped measure, as that's easier to experiment with.
b. It returns the first year's Name, as that's easier to see. Eventually I'll just return the member itself, and do an IS comparison against the year hierarchy .CurrentMember in the other calculated member calculations.
The problem I expected, which has happened, is that I only want this measure to be calculated once, over the whole cube. But when I used it in a query, it obviously reacts to the context. For example, if I stick the Products dimension on ROWS, the value of this measure will be different for each row, because each product's earliest order date is different.
That is of course useful, but it's not what I want. Is there some way to force this measure to ignore the query context, and always return the same value?
I looked into SCOPE_ISOLATION and SOLVE_ORDER, but they don't do what I'm trying to do here.
I suppose I could specify a tuple of Dimension1.All, Dimension2.All.... DimensionN.All, covering all dimensions in the cube, but that seems messy and fragile.
I think you might be able to accomplish this with static sets. Here is an example using Adventure Works that produces the same first year regardless of context:
WITH STATIC SET FirstYear AS
HEAD
(
NONEMPTY([Date].[Calendar Year].[Calendar Year].MEMBERS, [Measures].[Internet Sales Amount])
, 1
)
MEMBER FirstYearName AS
FirstYear.ITEM(0).NAME
SELECT
[Measures].[FirstYearName] ON COLUMNS
, [Date].[Calendar Year].[Calendar Year].MEMBERS
//Add as many dimensions as you like here...for example
* [Product].[Product].[Product].MEMBERS
ON ROWS
FROM
[Adventure Works]
;
Example output:
That should hopefully put you on the right track.
I have yearly sales goals in a measure called "Target" and a date dimension called DimCalendar.
Looking at the underlying data, I'm thinking I should get a value different than what the below query returns. It's my understanding that this query will get the value for the "Target" measure where the associated year is 2016 (one year in the future or -1) and for a specific account.
SELECT
{[Measures].[Target]} on columns,
{ParallelPeriod(
[DimCalendar].[Year].[Year]
,-1
,[DimCalendar].[Year].&[2015])} on rows
FROM [MySalesCube]
WHERE { [Account].[Account].&[2025] }
This query returns
1944768
However, the underlying data seems to add up to only 162064
Nope, looks like there is an issue with the data after all after using the cube browser. Got to go revisit my ETL process.
This is what you have specified:
ParallelPeriod(
[DimCalendar].[Year].[Year]
,-1
,[DimCalendar].[Year].&[2015])
It means the following:
Take the year 2015
Then jump the specified number of periods, in your case -1, using the level specified, in your case [Year]
The following should (I think) be a simplified but equivalent version - if the first argument is missed out then it just uses the level of the third argument:
ParallelPeriod(
-1
,[DimCalendar].[Year].&[2015])
Although I think you can just use lag to make everything more readable:
[DimCalendar].[Year].&[2015].LAG(-1)
Then again there is no point using 1 or -1 inside lag, as we have the functions NEXTMEMBER and prevMEMBER this could just be simplified to the following:
[DimCalendar].[Year].&[2015].NEXTMEMBER
I am trying to apply some Time Intelligence functions in my PowerPivot workbook concerning projects and money received for them. I have three relevant tables; Matters, Payments, and a Date Table.
Each matter has a creationDate, and a closureDate(from a linked table). Likewise, each payment has a date. I have reporting set up decently, but am now trying to use Time intelligence to filter this a bit more clearly.
How can I set a PowerPivot Pivot Table up so that the only Matters which show are those which existed within the period selected. e.g. If I select a slicer for 2014, I don't want to show a matter created in 2015, or one which was closed in 2013. The matter should have been active during the period specified.
Is this possible?
You want to show all the matters EXCEPT those where the CreationDate is after the upper limit of the date range you are looking at or the ClosureDate is before the lower limit of the date range you are looking at.
Assuming you have a data structure like this, where the left-hand table is the Matters and the right-hand one is the Payments:
If you have a calculated field called [Total Payments] that just adds up all the payments in the Payments table, a formula similar to this would work:-
[Payment in Range]:=IF(OR(MIN(Matters[Creation Date])>MAX('Reporting Dates'[Date]),MAX(Matters[Closure Date])<MIN('Reporting Dates'[Date])),BLANK(),[Total Payments])
Here is the result with one month selected in the timeline:
Or with one year selected in the year slicer:
NOTE: in my example, I have used a disconnected date table.
Also, you will see that the Grand Total adds up all the payments because it takes the lowest of all the creation dates and the highest of all the closure dates to determine whether to show a total payment value. If it is important that the Grand Total shows correctly, then an additional measure is required:
[Fixed Totals Payment in Range]:=IF(COUNTROWS(VALUES(Matters[Matter]))=1,[Payment in Range],SUMX(VALUES(Matters[Matter]),[Payment in Range]))
Replace the [Payment in Range] in your pivot table with this new measure and the totals will show correctly, however, this will only work if Matters[Matter] is used as one of the fields in the pivot table.
Use filters & the calculate function.
So, if you're Summing payments, it would look like.....
Payments 2014:= CALCULATE( SUM([Payments]), DateTable[Year]=2014)
The Sum function takes the entirety of payments & the filter function will only capture payments w/in 2014, based on the data connected to your date table.