Creating a calculated column (not aggregate) that changes value based on context SSAS tabular DAX - ssas

Data: I have a single row that represents an annual subscription to a product, it has an overall startDate and endDate, there is also third date which is startdate + 1 month called endDateNew. I also have a non-related date table (called table X).
Output I'm looking for: I need a new column called Categorisation that will return 'New' if the date selected in table X is between startDate and endDateNew and 'Existing' if the date is between startDate and endDate.
Problem: The column seems to evaluate immediately without taking in to account the date context from the non-related date table - I kinda expected this to happen in visual studio (where it assumes the context is all records?) but when previewing in Excel it carries through this same value through.
The bit that is working:I have an aggregate (an active subscriber count) that correctly counts the subscription as active over the months selected in Table X.
The SQL equivalent on an individual date:
case
when '2015-10-01' between startDate and endDateNew then 'New'
when '2015-10-01' < endDate then 'Existing'
end as Category
where the value would be calculated for each date in table X
Thanks!
Ross

Calculated columns are only evaluated at model refresh/process time. This is by design. There is no way to make a calculated column change based on run-time changes in filter context from a pivot table.

Ross,
Calculated columns work differently than Excel. Optimally the value is known when the record is first added to the model.
Your example is kinda similar to a slowly changing dimension .
There are several possible solutions. Here are two and a half:
Full process on the last 32 days of data every time you process the subscriptions table (which may be unacceptably inefficient).
OR
Create a new table 'Subscription scd' with the primary key from the subscriptions table and your single calculated column of 'Subscription Age in Days'. Like an outrigger. This table could be reprocessed more efficiently than reprocessing the subscriptions table, so process the subscriptions table as incrementals only and do a full process on this table for the data within the last 32 days instead.
OR
Decide which measures are interesting within the 'new/existing' context and write explicit measures for them using a dynamic filter on the date column in the measures
eg. Define
'Sum of Sales - New Subscriptions',
'Sum of Sales - Existing Subscriptions',
'Distinct Count of New Subscriptions - Last 28 Days', etc

Related

DAX formula calculate dates between first transaction and (first transaction + 6 months)

Background: I have a column in a Customer dimension with a static date(e.g '2013-01-01').
This column is the result of a calculation that gets the first transaction date ever made by that certain customer. This customer dimension is linked to a fact table containing reportdate as a date column linked to a date dimension.
Goal: I want to make a calculated measure that, based on a sum of amount measure, calculates the result based on a given period between start_date(First transaction date), end_date (first transaction date + 6 months).
All i get is "cannot be determined in the current context" warnings and cannot get my head around to fix it.
All help is welcome!
Thanks in advance,
/Blixter
SOLVED I replicated the logic from the calculated measure found in the Customer table.
=CALCULATE([SumAmount];DATESBETWEEN(DimDate[Date];FIRSTDATE(‌​FactTable[Reportdate‌​]);DATEADD(FIRSTDATE‌​(FactTable[Reportdat‌​e]);5;MONTH)))

Creating a DAX pattern that counts days between a date field and a month value on a chart's x-axis

I am struggling with a DAX pattern to allow me to plot an average duration value on a chart.
Here is the problem: My dataset has a field called dtOpened which is a date value describing when something started, and I want to be able to calculate the duration in days since that date.
I then want to be able to create an average duration since that date over a time period.
It is very easy to do when thinking about the value as it is now, but I want to be able to show a chart that describes what that average value would have been over various time periods on the x-axis (month/quarter/year).
The problem that I am facing is that if I create a calculated column to find the current age (NOW() - [dtOpened]), then it always uses the NOW() function - which is no use for historic time spans. Maybe I need a Measure for this, rather than a calculated column, but I cannot work out how to do it.
I have thought about using LASTDATE (rather than NOW) to work out what the last date would be in the filter context of any single month/quarter/year, but if the current month is only half way through, then it would probably need to consider today's date as the value from which to subtract the dtOpened value.
I would appreciate any help or pointers that you can give me!
It looks like you have a table (let's call it Cases) storing your cases with one record per case with fields like the following:
casename, dtOpened, OpenClosedFlag
You should create a date table with on record per day spanning your date range. The date table will have a month ending date field identifying the last day of the month (same for quarter & year). But this will be a disconnected date table. Don't create a relationship between the Date on the Date table and your case open date.
Then use iterative averagex to average the date differences.
Average Duration (days) :=
CALCULATE (
AVERAGEX ( Cases, MAX ( DateTable[Month Ending] ) - Cases[dtopened] ),
FILTER ( Cases, Cases[OpenClosedFlag] = "Open" ),
FILTER ( Cases, Cases[dtopened] <= MAX ( DateTable[Month Ending] ) )
)
Once you plot the measure against your Month you should see the average values represented correctly. You can do something similar for quarter & year.
You're a genius, Rory; Thanks.
In my example, I had a dtClosed field rather than an Opened/Closed flag, so there was one extra piece of filtering to do to test if the Case was closed at that point in time. So my measure ended up looking like this:
Average Duration:=CALCULATE(
AVERAGEX(CasesOnly, MAX(DT[LastDateM]) - CasesOnly[Owner Opened dtOnly]),
FILTER(CasesOnly, OR(ISBLANK(CasesOnly[Owner Resolution dtOnly]),
CasesOnly[Owner Resolution dtOnly] > MAX(DT[LastDateM]))),
FILTER(CasesOnly, CasesOnly[Owner Opened dtOnly] <= MAX(DT[LastDateM]))
)
And to get the chart, I plotted the DT[Date] field on the x-axis.
Thanks very much again.

Filter PowerPivot based on multiple Date Criteria

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.

How to do bitwise operations in SSAS cube for aggregations using MDX

I want to model a fact table for our users to help us calculate DAU (Daily active Users), WAU (Weekly active users) and MAU (Monthly active users).
The definitions of these measures are as follows:
1. DAU are users who is active every day during last 28 days.
2. WAU are users who are active at least on one day in each 7 days period during last 28 days
3. MAU are users who are active at least 20 days during last 28 days
I have built a SSAS cube with my fact table and user dimension table as follows
Fact : { date, user_id, activity_name}
Dimension: { date, user_id, gender, age, country }
Now I want to build a cube over this data so that we can see all the measures in any given day for last 28 days.
I thought of initially storing 28 days of data for all users in the SQL server and then do count distinct on date to see which measures they fall into.. but this proved very expensive since the data per day is huge..almost 10 millions rows.
So my next thought was to model the fact table (before moving it to SQL) such that it has a new column called "active_status" which is a 32 bit binary type column.
Basically, I'll store a binary number (or decimal equivalent) like 11000001101111011111111111111 which has a bit set on the days the user is active and off on the days user is not active.
This way I can compress 28 days worth of data in a single day before loading into data mart
Now the problem is , I think MDX doesn't support bitwise operations on columns in the expressions for calculated members like regular SQL does. I was hoping to create calculated measures daily_active_users, weekly_active_users and monthly_active_users using MDX that looks at this active_status bit for the user and does bitwise operation to determine the status.
Any suggestions on how to solve this problem? if MDX doesn't allow bitwise, what else can I do SSAS to achieve this.
thanks for the help
Additonal notes:
#Frank
Interesting thought about using a view to do the conversion from bitset to a dimension category..but I'm afraid it won't work. Because I have few dimensions connected to this fact table that have many-many relationships..for ex: I have a dimension called DimLanguage and another dimension called DimCountry and they have many-many relationship. And what ultimately I would like to do in the cube is to calculate the DAU/WAU/MAU which are COUNT(DISTINCT UserId) based on the combination of dimensions. So for ex; If a user is not MAU for dimension country US because he is only active 15 days out of 28 ....but he will be considered
You do not want to show the bitmap data to the users of the cube, but just the categories DAU, WAU, MAU, you should do the conversion from bitmap to category on data loading time. Just create a dimension table containing e. g. the following data:
id category
-- --------
1 DAU
2 WAU
3 MAU
Then define a view on your fact table that evaluates the bitmap data, and for each user and each date just calculates the id value of the category the user is in. This is then conceptually a foreign key to the dimension table. Use this view instead of the fact table in your cube.
All the bitmap evaluations are thus done on the relational side, where you have the bit operators available.
EDIT
As your requirement is that you need to aggregate the bitmap data in Analysis Services using bitwise OR as the aggregation method, I see no simple way to do that.
What you could do, however, would be to have 28 single columns, say Day1 to Day28, which would be either 0 or 1. These could be of type byte to save some space. You would use Maximum as aggregation method, which is equivalent to binary OR on a single bit.
Then, it would not be really complex to calculate the final measure, as we know the values are either zero or one, and thus we can just sum across the days:
CASE
WHEN Measures.[Day1] + ... + Measures.[Day28] = 28 THEN 'DAU'
WHEN Measures.[Day1] + ... + Measures.[Day7] >= 1 AND
Measures.[Day8] + ... + Measures.[Day14] >= 1 AND
Measures.[Day15] + ... + Measures.[Day21] >= 1 AND
Measures.[Day22] + ... + Measures.[Day28] >= 1 THEN 'WAU'
WHEN Measures.[Day1] + ... + Measures.[Day28] >= 20 THEN 'MAU'
ELSE 'Other'
END
The order of the clauses in the CASE is relevant, as the first condition matching is taken, and your definitions of WAU and MAU have some intersection.
If you have finally tested everything, you would make the measures Day1 to Day28 invisible in order not to confuse the users of the cube.

Single aggregate column / running value sum on chart

We're currently porting some excel reports to SSRS. One of those reports has a graph where the last column is the MTD (Month to date) average for both series (Availability and Availability Goal) just like the example below:
I did some research about RunningValue() but whenever I did it it would add a second bar to my graph (the running value would have the same group).
Is it possible to have only one aggregate column (just like the screenshot) ?
Thanks in advance,
One way would be to force the average through the SQL query. For example, if your resulting table shows days of the month, and the Availability value, you could UNION a "dummy" day (max days of the month + 1) with the averaged value. You can either add an addition column to your SQL for the label names, i.e. the "dummy" day would show "Average", or in SSRS you can change the Label expression to replace the last value with a text.