SSAS (Tabular) / DAX - Calculate measure over time / Rolling distinct count - ssas

I've a question about a rolling distinct count. I'm trying to calculate the latest 30 weeks (210 days) from a specific date (eg. Specific date = 18-02-2019 distinct count from 23-07-2018).
I've found a website/blog where this is explained, https://radacad.com/datesinperiod-vs-datesbetween-dax-time-intelligence-for-power-bi. But in some weird way, my calculation is not working.
My DAX expression:
Aantal mutaties afgelopen 30 weken:=
CALCULATE(
DISTINCTCOUNT(FCT_KlantReis_Mutatie[Mutatie]);
DATESINPERIOD(
FCT_KlantReis_Mutatie[Mutatiedatum];
LASTDATE(FCT_KlantReis_Mutatie[Mutatiedatum]) ;-210;DAY)
)
But in Excel (and PowerBI) I get the following result:
The table is linked to a date dimension. My guess is that it must be posible, but how...
Thanks in advance for the help.

Related

MDX - Filter different measures using different date intervals

This is similar to another question I made (MDX - Running Sum over months limited to an interval) but I feel that I was going off track there.
Let me start again.
I have a calculated measure
MEMBER [Measures].[m_active] AS ([Measures].[CardCount], [Operation].[Code].[ACTIVATION])
That I want to filter on a short interval (let's say from 10 January 2016 to 20 August 2017, those are parametrized)
and another calculated measure that i want to filter since the beginning of date dimension (1st January 2010) to the end of last filter (20 August 2017 in this case), this measure is running sum of all the precedent
MEMBER [Measures].[tot_active] AS (
SUM({[Calendar.YMD].[2010].Children}.Item(0):[Calendar.YMD].CurrentMember, ([Measures].[CardCount], [Operation].[Code].[ACTIVATION]))
On the columns I have this calculated dimensions and on the rows I have months (in the small interval range) and another dimension crossjoined
SELECT
{[Measures].[m_active], [Measures].[tot_attive]} ON COLUMNS,
NonEmptyCrossJoin(
{Descendants([Calendar.YMD].[2016].[Gennaio]:[Calendar.YMD].[2017].[Agosto], [Calendar.YMD].[Month])},
{Descendants([CardStatus.Description].[All CardStatus.Descriptions], [CardStatus.Description].[Description])}
) on ROWS
If I put a date range in the WHERE clause the first member is perfect but i ruin the second, how can I make the second member ignore the WHERE clause? Or is there another solution?
Without testing I'm a little bit unsure of the behaviour, but did you try moving the filter from a WHERE clause into a subselect?
Subselects are formed like this:
...
FROM (
SELECT
<date range for filter> ON 0
FROM cubeName
)

SQL Average of total days in DATA per month

I have a SQL question.
I am trying to find the average injection volume per month. Currently my code takes the sum of all days of injection, and divides them by the TOTAL DAYS in the month.
Sum(W1."INJECTION_VOLUME" /
EXTRACT(DAY FROM LAST_DAY(W1."INJECTION_DATE"))) AS "AVGINJ"
This is not what I wanted.
I need to take the injection_volume and divide by the total days in the DATA .
ie. right now the data only 8 days of injection volume, lets say it is 3000.
So right now the sql is 3000/31.
I need to have it be 3000/8 (the total days in the data for the current month.)
Also, this should only be for the current month. All other completed months should be divided by the total days in the month.
Use
SELECT
SUM(W1.INJECTION_VOLUME) / COUNT(DISTINCT MyDateField)
FROM MyTable
WHERE X=Value
This gives you what you're after
SUM(W1.INJECTION_VOLUME) is the total volume for the dataset
Gives you the number of days, no matter how many records you have
COUNT(DISTINCT MyDateField)
So if you have 100 records but only 5 actual unique days in this time, this expression gives you 5
Note that this kind of calc is normally worked out with
SUM(A) / SUM(B)
not
SUM(A/B)
They give you completely different answers.
In order to get the average of the data for the current month you will need to divide by the count in the month:
SUM(`W1`.`INJECTION_VOLUME` / COUNT(EXTRACT(YEAR_MONTH FROM `W1`.`INJECTION_DATE`)))
To get all other data as the full month you'll need to combine your code:
SUM(`W1`.`INJECTION_VOLUME` / EXTRACT(DAY FROM LAST_DAY(`W1`.`INJECTION_DATE`)))
With an IF. So something like this:
SUM(
IF(
EXTRACT(YEAR_MONTH FROM `W1`.`INJECTION_DATE`) = EXTRACT(YEAR_MONTH FROM NOW()),
`W1`.`INJECTION_VOLUME` / COUNT(EXTRACT(YEAR_MONTH FROM `W1`.`INJECTION_DATE`)),
`W1`.`INJECTION_VOLUME` / EXTRACT(DAY FROM LAST_DAY(`W1`.`INJECTION_DATE`)
)
)
Note: this is untested and I'm not sure about the RDBMS you are using so you may need to change the code slightly to make it work.

Year wise Average days SQL

Today i have below problem while perform an sql query. Please find below data.
I perform SQL query on my table and get the below resulted output. i perform Group by on ID, Name, Week, Year, Days now i want the Days column as average of All Days based on year column. means there is multiple value of year is exist so i need Avg of Days data in all rows of DAYS for particular row. expected result as per below.
Thanks in Advance!!!
Write in comment if you have any query.
You can use OVER:
SELECT
*,
AVG(Days) OVER (PARTITION BY LEFT(Year, 4)) AvgDays
FROM
Tbl
Note: Just grouped by year (2016)

AVG(EXISTING()) syntax error

I want to calculate sales for promotion using it's date. I need 3 measures, avg sales from 21 days before promotion start date, sales in between of promotion's start and end date, and sales from 21 days after promotion's end date.
Why Visual Studio highlights avg in code below?
CREATE MEMBER CURRENTCUBE.[Measures].[Sales in promotion]
AS Avg(Existing([Promotion].[Promotion name].[Promotion name]),[Measures].[Sales]), ...
Same in here:
CREATE MEMBER CURRENTCUBE.[Measures].[Sales before promotion]
AS (EXISTING([Promotion].[Promotion name].[Promotion name]), AVG(strtomember("[Date].[Date].&["+ [Promotion].[Date].currentmember.member_key+"]").lag(21) : strtomember("[Date].[Date].&["+ [Promotion].[Date From].currentmember.member_key+"]"),
[Measures].[Sales])) ...
If I do sum(existing()) in first measure, the sum is calculated correctly, but it doesn't allow me to get average.
EXISTING will only help if [Promotion] is part of your query in either the WHERE or SELECT clause. If it is not included in either of these clause then EXISTING will be finding 1 member - the All member.
You could try NonEmpty and maybe move the period logic into a custom set?
WITH
SET [PERIOD] AS
STRTOSET(
"[Date].[Date].&["+ [Promotion].[Date].currentmember.member_key+"].lag(21)
:
[Date].[Date].&["+ [Promotion].[Date From].currentmember.member_key+"]"
)
From the code you posted I cannot tell if you want a daily average or and average per promotion ? Say there were 2 promotions over the 21 days does this mean you want (Total/2/21) ?

Query to find a weekly average

I have an SQLite database with the following fields for example:
date (yyyymmdd fomrat)
total (0.00 format)
There is typically 2 months of records in the database. Does anyone know a SQL query to find a weekly average?
I could easily just execute:
SELECT COUNT(1) as total_records, SUM(total) as total FROM stats_adsense
Then just divide total by 7 but unless there is exactly x days that are divisible by 7 in the db I don't think it will be very accurate, especially if there is less than 7 days of records.
To get a daily summary it's obviously just total / total_records.
Can anyone help me out with this?
You could try something like this:
SELECT strftime('%W', thedate) theweek, avg(total) theaverage
FROM table GROUP BY strftime('%W', thedate)
I'm not sure how the syntax would work in SQLite, but one way would be to parse out the date parts of each [date] field, and then specifying which WEEK and DAY boundaries in your WHERE clause and then GROUP by the week. This will give you a true average regardless of whether there are rows or not.
Something like this (using T-SQL):
SELECT DATEPART(w, theDate), Avg(theAmount) as Average
FROM Table
GROUP BY DATEPART(w, theDate)
This will return a row for every week. You could filter it in your WHERE clause to restrict it to a given date range.
Hope this helps.
Your weekly average is
daily * 7
Obviously this doesn't take in to account specific weeks, but you can get that by narrowing the result set in a date range.
You'll have to omit those records in the addition which don't belong to a full week. So, prior to summing up, you'll have to find the min and max of the dates, manipulate them such that they form "whole" weeks, and then run your original query with a WHERE that limits the date values according to the new range. Maybe you can even put all this into one query. I'll leave that up to you. ;-)
Those values which are "truncated" are not used then, obviously. If there's not enough values for a week at all, there's no result at all. But there's no solution to that, apparently.