How to create weekly YoY metric in AWS QuickSight? - data-visualization

I am trying to calculate a sum of a column for a specific calendar week, and want to compare that to the same week in the previous year.
So let's say I have the sum of WK21 for 2020 is 1000 and sum of WK21 in 2019 is 800. The field should return: 200.
Attached is how my dataset looks like.
I would like to sum the credit per WK for each segment, and see how the difference is to the sum of that week for that same segment, in the previous year. Later on I would change the difference to percentDifference, but I assume the main formula is the same.
Is that easy doable?
Tried this (percentDifference) for WoW (in the same year), and it worked using this formula:
percentDifference(sum({credit}),[{wk} ASC],-1,[{year}, industry, segment])
But when trying for weekly YoY the following formula, it didnt work (-52 because 52 weeks in year):
percentDifference(sum({credit}),[{wk} ASC, year ASC],-52,[industry, segment])
PS: for the country, I didnt take that in consideration, as I want to filter for the countries I want later on...

For Year-on-year difference create a calculated field like the following
difference(sum({credit}), [{wk} ASC, {year} ASC], -1, [{Industry}, {Segment}])
For year-on-year percentage difference your calculated field would be
percentDifference(sum({credit}), [{wk} ASC, {year} ASC], -1, [{Industry}, {Segment}])
This is because the lookup index in the function (-1) is based on the sort of the rows (sort order in the square brackets in the function)
Source: percentDifference and difference QuickSight Docs

Try -100 instead of -52. Since the 'wk' field is not a date-defined field, it is probably just considering 'wk' as an int.

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.

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.

How to Calculate Sum untill start of month of a given date in DAX

I would like to calculate Sum(QTY) until the start date of the month for a given date.
Basically I can calculate Sum(QTY) until given date in my measure like:
SumQTYTillDate:=CALCULATE(SUM([QTY]);FILTER(ALL(DimDateView[Date]);DimDateView[Date]<=MIN(DimDateView[Date])))
But I also would like to calculate Sum(QTY) for dates before 10/1/2015 - which is the first date of selected Date's month. I have changed above measure and used STARTOFMONTH function to find first day of the month for a given date like;
.......DimDateView[Date]<=STARTOFMONTH(MIN(DimDateView[Date]))))
but not avail, it gives me
"A function ‘MIN’ has been used in a True/False expression that is
used as a table filter expression. This is not allowed."
What am I missing? How can I use STARTOFMONTH function in my measure?
Thanks.
STARTOFMONTH() must take a reference to a column of type Date/Time. MIN() is a scalar value, not a column reference. Additionally, your measure wouldn't work, because STARTOFMONTH() is evaluated in the row context of your FILTER(). The upshot of all this is that you would get a measure which just sums [QTY] across the first of every month in your data.
The built in time intelligence functions tend to be unintuitive at best. I always suggest using your model and an appropriate FILTER() to get to what you want.
In your case, I'm not entirely sure what you're looking for, but I think you want the sum of [QTY] for all time before the start of the month that the date you've selected falls in. In this case it's really easy to do. Add a field to your date dimension, [MonthStartDate], which holds, for every date in the table, the date of the start of the month it falls in. Now you can write a measure as follows:
SumQTY=SUM(FactQTY[QTY])
SumQTYTilStartOfMonth:=
CALCULATE(
[SumQTY]
;FILTER(
ALL(DimDateView)
;DimDateView[Date] < MIN(DimDateView[MonthStartDate])
)
)

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.