Calculate Time Interval in SSAS based on difference between current row time and previous row time - ssas

I have an SSAS Cube which tracks the movement of items in a warehouse. Items are scanned into various locations, so, we have a date and time (HH:MM:SS) that the item is scanned. We want to be able to create a calculated measure, which is not pre-defined on the fact table, as we would like it to be dynamic, based on the attributes the query is sliced by.
So, in order to accommodate that, I figured I would create a SET which has the intersection of valid dates and valid times, like this:
WITH SET [Valid Date]
AS FILTER([WMSR Date].[Full Date].[Full Date].MEMBERS,[Measures].[Fact Scans Count]>0)
SET [Valid Time]
AS FILTER(([Valid Date]*[Time].[Full Time].[Full Time].MEMBERS),[Measures].[Fact Scans Count]>0)
So, if I run this:
SELECT {[Measures].[Fact Scans Count]} ON COLUMNS,
[Valid Time] ON ROWS
FROM
WarehouseCube
WHERE
[Piece].[Dim ID Key].&[1127981]
It will give me, for a given item, the date/time of the scan, and the count. How do I get the date/time from the previous row?
Thanks in advance!

You could use
[ValidTime].Item(Rank(([WMSR Date].[Full Date].CurrentMember, [Time].[Full Time].CurrentMember),
[ValidTime])
- 2
)
The Rank function returns the position of a tuple within a set. The Item function returns a tuple at a position from a set.
As Rank returns 1 for the first item, while Item expects 0 for the first item, and you want to go back one position, you need to subtract two.

Related

How to get records month wise on rollover calender

I am using following query to get records count on month wise and it is working fine:
SELECT MONTH(dte_cycle_count) MONTH, COUNT(*) COUNT
FROM inventory
WHERE YEAR(dte_cycle_count)='2021' --OR (MONTH(dte_cycle_count) = '1' OR MONTH(dte_cycle_count) = '12')
GROUP BY MONTH(dte_cycle_count);
Problem:
Now I need to bind rollover calendar so user can scroll or click on next or previous button the next 12 Months record will be visible.
eg. Current month is MARCH, So default records will be from APR2020 to MARCH2021. If user click on previous then records will come MAR2020 to FEB2021.
How I can achieve this?
Please let me know if need more information. I will try my best to provide.
I think what you are after is a date list from which to join to your inventory table.
Like a numbers table, build a static table with columns for date, year, month, populated from whenever you need to far in the future.
You then select from this, applying your filtering range critera, and join to your inventory table.
For an efficient query, ideally your inventory table should have the relevant date portions eg year and month stored to match.
You don't want to be using functions on a datetime to extract the year or month as this is not sargable and will not allow any index to be used for a seek lookup.

Display all dates even if there is no data

I am attempting to display all the dates within a range even if they do not have data for the particular date.
Our employees do work 24/7 365 ( like everyone else) so there are dates within my time range that wont pop up. What i have tried is to add and exception that states even if the date has a null to display that particular date.
Currently i have a crosstab with the row being the numbers of items completed and the columns being the date that the item was completed.
For a visual:
04/01/19 04/02/19 04/03/19
1 2 3
I would like to continue that till the end of my range (the month) but my data skips if nothing was completed for that date.
What i currently have:
04/01/19 04/04/19 04/05/19
1 6 8
For the rows I have this in the formula bar for my row.
If [Items Completed]> 0 Then [Items Completed)] Else 0
For the columns I have this in my formula bar
If IsNull([Completed Date]) then 0 Else [Completed Date]
Thinking this would give me a 0 in those columns where nothing was done.
You need to create a variable and use the TimeDim function like this...
All Dates = TimeDim([Completed Date])
Then replace [Completed Date] in your table with the [All Dates] variable. You can name it whatever you want. This will result in blank values for the dates for which you do not have data. If you want to have zeroes display for the dates with no data you can apply a custom format setting "Undefined" to "0".
You can find a more thorough explanation with possible variations here.
Enjoy!
The TimeDim method was the basis for me achieving what I needed - namely a line chart that displayed zero values if no one had completed a training course on a particular date in my range. I work in Learning Management System software so this is often required.
The object in my case is called [Course Completed Date (Success)], so here's my variable (which is a dimension, not a measure):
=TimeDim([Course Completed Date (Success)])
Note in my screenshot how the zeros and now displayed. Previously they were missing.

How to right click table to show values?

In a pivot table that plots values against a timeline it is possible to right-click the table, select "Show values as..." and have them appear as a percentage of a particular day.
I'm trying to recreate the same behaviour using DAX measures: I would like to have a measure that shows each day's price as a percentage of the first day of the year.
I've successfully created a measure that correctly identifies the first date of the year, i.e. the baseline:
FDate:=CALCULATE(FIRSTDATE(Prices[Date]),ALLEXCEPT('Calendar','Calendar'[Year]))
However, I can't figure out how to use this FDate to get that day's price (needed as the baseline for further calculations):
CALCULATE([Sum of Price], ALLEXCEPT('Calendar','Calendar'[Year]), FILTER('Prices', 'Prices'[Date]=[FDate])) returns each day's price, not the first date's.
CALCULATE([Sum of Price], FILTER(ALLEXCEPT('Calendar','Calendar'[Year]),'Calendar'[Date]=[FDate])) ignores the YEAR report filter and returns the price of the very first date in my calendar table and not the first date in the year I've filtered for.
Any pointer in the right direction would be greatly appreciated!
Thanks
Here's the solution:
VAR FirstDate = [FDate]
RETURN(
CALCULATE([Price],
FILTER(ALLEXCEPT('Calendar','Calendar'[Year]),'Calendar'[Date]=FirstDate))
)
Variables allow you to define measure in a certain filter context but to leave it unaffected by subsequent filter contexts - that at least is my layman's understanding.
More info here: https://www.sqlbi.com/articles/variables-in-dax/

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.

Return the last non empty member of date dimension, based on other dimension

New to MDX and a bit bewildered...
We have a cube with an excel pivot table over the top for reporting. What I need to provide is an easy means for people to see the max (last) member of the relevant date dimension when also sliced against another dimension, and the row count on that day.
I have a "booking count" measure and I want to see the number of bookings on the last date I had any bookings for any other dimensions children. If that makes sense.
The closest i've got so far is this:
select [Measures].[Booking Count] on 0, filter(([Sub Channel].[Channels].[Channel].members, [Booking Date].[Date].children), not isempty([Measures].[Booking Count])) on 1 from myCube
But I can't then use LastChild or similar to get the last member of each channel.
Hope that makes sense! Huge thanks in advance for any help.
You are nearly there, just use the Tail function to get the last date from your set:
select [Measures].[Booking Count]
on 0,
Tail(filter(([Sub Channel].[Channels].[Channel].members, [Booking Date].[Date].children),
not isempty([Measures].[Booking Count])))
on 1
from myCube