ParallelPeriod in MDX Query with CurrentMember - sql-server

I am trying to predict the number of rooms that my organisation will need to book on the basis of how many students we have enrolled for the busy part of our year.
The first part of this problem is calculating the relative decrease/increase in student numbers in this year vs. last year and using that to extrapolate student numbers for this year.
To this end, I am trying to measure the following:
A running total of enrollments in the weeks of the year leading up to a range of start dates e.g. how many students enrolled in weeks 1,2,3... of 2016 who will be here between October and December for a given year
Calculate the percentage increase/decrease over the previous years in student numbers
I have the following query:
WITH MEMBER [Measures].[Period Growth] AS
(
[Measures].[Enrolments By Week],
ParallelPeriod([Weekly Enrolments Date].[ISO Week Calendar].[ISO Year],
1,
[Weekly Enrolments Date].[ISO Week Calendar].[ISO Week].currentmember)
)
SELECT NON EMPTY { [Measures].[Enrolments By Week], [Measures].[Period Growth] } ON COLUMNS,
NON EMPTY { FILTER([Weekly Enrolments Date].[ISO Week Calendar].[ISO Week].&[201738] :
[Weekly Enrolments Date].[ISO Week Calendar].[ISO Week].&[201752],
Cint([Term Record Creation].[ISO Week Number Of Year].CurrentMember.Member_Key) <= 10 --Cint( STRTOMEMBER(#ToISOWeekNumberOfYear, CONSTRAINED).Member_Key )
OR
Cint([Term Record Creation].[ISO Year].CurrentMember.Member_key) <
Cint([Term Start Date].[ISO Year].CurrentMember.Member_key)) } ON ROWS
FROM [Enrolments]
However, I am getting #Error for the calculated member when I set the member expression in the ParallelPeriod as CurrentMember. If I change the CurrentMember to a value like .&[201642] the error disappears - why is this? How can I get the same week in the previous year as a comparison for each week row of the current year?
In addition, how can I get the percentage change for each week relative to the previous year in the same week, while avoiding divide by 0 errors?

To me this looks like a level:
[Weekly Enrolments Date].[ISO Week Calendar].[ISO Week]
So yes this is valid and there will not be an error:
[Weekly Enrolments Date].[ISO Week Calendar].[ISO Week].&[201642]
But I don't think the CURRENTMEMBER function can be applied to a level expression - if you just shorten to the following it might be happier:
[Weekly Enrolments Date].[ISO Week Calendar].currentmember

Related

How to do rolling weeks based on date?

I'm currently at a data analyst student job following an internship and I have do to reports based on the ticketing tool of the company, so, I'm using a pre-calculated table (the administrator have made pre-calculated tables based on his querys).
I have week table with all I need and I have to do a rolling 26 week report.
Because it is calculated that are historized and I don't have creation_date or end_date column.
I can't manage to do this can you help me with this ?
Actually, as a rolling query, if I have 18 weeks for 2021 I will need the 8 weeks last weeks of 2020.
I have this columns : Closed, Week, Month, Backlog... and I need it just for Closed.
I've tried this :
SELECT SUM(CLOSED), WEEK, MONTh, YEAR
FROM E_GROUPE_INTERVENANT_SEMAINE_HISTORY
WHERE MONTH >= Month(getdate())-6
AND YEAR <= YEAR(getdate())
EDIT : The weeks range values 1 trough 53 or 52 it depends on the year, the weeks are weeks of month, I've tried this
SELECT SUM(CLOSED), WEEK, MONTH, YEAR
FROM E_GROUPE_INTERVENANT_SEMAINE_HISTORY
WHERE
YEAR(DATEADD(WEEK, -26, GETDATE())) = YEAR(GETDATE()) - 1
AND
YEAR = YEAR(GETDATE())
AND
MONTH <= Month(DATEADD(WEEK, -26, GETDATE()))
)
group by WEEK, MONTH, YEAR
order by WEEK, YEAR
But I'm only getting week for the current year the previous year doesn't show.
I wonder if it's even possible to have the last year because without the pre-calculated tables I could get the last year with my querys but they want me to use this table.
Thank you for your help.
I don't see what your week value is but this will get you close:
SELECT SUM(CLOSED), WEEK, MONTH, YEAR
FROM E_GROUPE_INTERVENANT_SEMAINE_HISTORY
WHERE (--CURRENT YEAR WHEN YEAR IS NOT CROSSED
YEAR(DATEADD(WEEK, -18, GETDATE())) = YEAR(GETDATE())
AND
YEAR = YEAR(GETDATE())
AND
MONTH >= Month(DATEADD(WEEK, -18, GETDATE()))
)
OR
( --LAST MONTHS OF LAST YEAR WHEN YEAR IS SPANNED
MONTH >= Month(DATEADD(WEEK, -18, GETDATE()))
AND
YEAR = YEAR(DATEADD(WEEK, -18, GETDATE()))
)
OR
(--ALL MONTHS FOR CURRENT YEAR WHEN YEAR IS CROSSED
YEAR(DATEADD(WEEK, -18, GETDATE())) = YEAR(GETDATE()) - 1
AND
YEAR = YEAR(GETDATE())
AND
MONTH <= Month(DATEADD(WEEK, -18, GETDATE()))
)

SQL server week ending Thursday range

I'm trying to show the DateTimeRaised field as a week ending Thursday. The FkIssueGroupID isn't unique but each row should have the same date. The MAX is being used to bring back a single row.
Select distinct w.fkIssueGroupID
,[FormDateTimeRaised] =MAX ([DateTimeRaised])
,[WEnd Raised - Thur]= max (CONVERT (date, DATEADD(dd, 5 - (DATEPART(dw, [DateTimeRaised])), [DateTimeRaised]) ))
Whilst the week ending value for Thursday is correct the week days contained within it don't line up i.e.:
Week ending Thursday will have a date of the 21/05/20 (Thursday) but the date values covered by the data are 18/05 to 24/05 (Mon-Sun). I want the date range covered to be 15/05 to 21/05 (Fri-Thur). How do i get the date range to shift from Mon-Sun to Fri-Thur?
You can set the first day of the week to Friday like this:
SET DATEFIRST 5;

SQL server: smoothed average of day of year

I have a subquery with avg reservoir inflow pr day of year (from 1-365). Now I would like to calculate a smoothed/moving average for each day of year in a new column.
Example: for january 1st (DayOfYear = 1) I would like to calculate a smoothed average of 21 days (10 pre and 10 post days). I.e an avg of days ranging from (356-11). For day of year 55 the avg should be calculated on days of the year ranging from (45-65).
Her is the unfinished query based on a subquery called 'sub' where the 10 years of inflow first are averaged on day of year;
DECLARE #Dager int ;
SET #Dager = 10; /* # days pre and post the actual day of year to be included in avg */
Select sub.Magasin, sub.DayOfYear, AVG(sub.Inflow) as AvgInflow
FROM (SELECT Date, Magasin, Datepart(dy,Date) as DayOfYear, Value as Inflow
FROM inputtable
WHERE Date >= DATEFROMPARTS(2008,1,1) and Date <= DATEFROMPARTS(2017,12,31)) sub
GROUP By sub.Magasin, sub.DayOfYear
ORDER BY sub.magasin, sub.DayOfYear
Without any sample data, I'm going to suggest this for SQL Server 2012+
(Your SQL looks like SQL Server 2012+)
SELECT
Magasin,
Datepart(dy,Date) AS DayOfYear,
AVG(Inflow) OVER (
PARTITION BY Magasin
ORDER BY YEAR(Date), Datepart(dy,Date)
ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING)
FROM
inputtable
WHERE
Date >= DATEFROMPARTS(2008,1,1) and Date <= DATEFROMPARTS(2017,12,31))

Decision based on what day of the week a date falls on

For any given date I need to determine what day of the week it is.
I already know how to get the day of the week with this DATENAME(dw,MyDate.Field)and the number of the day with this DATEPART(dw,MyDate.Field).
Once I've got the day of the week if it is before Wednesday I want to return that Wednesday's date.
If the day of the week is Wednesday or after then I want to return next Wednesdays date.
Monday is day 1 in my system.
Use DATEPART() to determine day of the week.
Use CASE() for the different cases.
Calculate the day delta. Hint: It's either 3-dw or 7+3-dw.
Use DATEADD() to get from the current day (returned by DATEPART) to Wednesday or Wednesday of next week.
the easiest way, without any calculating:
set datefirst 1;
with dates as (
select CAST('20170906' as datetime) d
union all
select DATEADD(day, 1, dates.d)
from dates
where DATEADD(day, 1, dates.d) <= '20170930'
)
select dates.d, DATEADD(day, v.valueToAdd, dates.d) nextWed
from dates
join (values(1,2),(2,1),(3,7),(4,6),(5,5),(6,4),(7,3))v(dayOfWeek,valueToAdd) on v.dayOfWeek = DATEPART(weekday, dates.d)
order by 1

MSSQL order by previous 7 days

I run this query in MSSQL to get the items, grouping by the last 7 days of the week:
SELECT COUNT(Date_Entered), DATENAME(WEEKDAY, Date_Entered)
FROM my_table
WHERE Board_Name = 'Board'
AND DATEDIFF(DAY,Date_Entered,GETDATE()) <= 7
GROUP BY DATENAME(WEEKDAY, Date_Entered)
In the result, days of the week are sorted in alphabetical order: Friday > Monday > Saturday > Sunday > Thursday > Tuesday > Wednesday
How do I sort by the normal/correct/common sense order, starting with the weekday of 7 days ago and ending with yesterday?
Ordering by MAX(Date_Entered) should work too:
SELECT
COUNT(Date_Entered),
DATENAME(WEEKDAY, Date_Entered)
FROM my_table
WHERE Board_Name = 'Board' AND DATEDIFF(DAY,Date_Entered,GETDATE()) <= 7
GROUP BY DATENAME(WEEKDAY, Date_Entered)
ORDER BY MAX(Date_Entered);
Normally you would want to order by the date ascending, but since you use an aggregate function you would need to group by the date which would ruin it, but since the max(date) in every group is the date you can do max(date) to order.
DATEPART is your friend, try it like this:
SELECT COUNT(Date_Entered), DATENAME(WEEKDAY, Date_Entered),DATEPART(WEEKDAY,Date_Entered)
FROM my_table
WHERE Board_Name = 'Board'
AND DATEDIFF(DAY,Date_Entered,GETDATE()) <= 7
GROUP BY DATEPART(WEEKDAY,Date_Entered),DATENAME(WEEKDAY, Date_Entered)
ORDER BY DATEPART(WEEKDAY,Date_Entered)
If you can't count on data being available for every week then you'd need to do something more based on date calculations. Off the top of my head I think this will be more reliable:
ORDER BY (DATEDIFF(dd, MAX(Date_Entered), CURRENT_TIMESTAMP) + 77777) % 7
EDIT: I wrote that not realizing that the data was already limited to a single week. I thought the intention was to group in buckets by day of week for a longer range of dates.
I'll also comment that to me it is more natural to do the grouping on cast(Date_Entered as date) rather than on a string value and I wouldn't be surprised if it's a more efficient query.

Resources