Max Nested Level SQL Server - Create Calendar type table - sql

I currently have a table which holds rate periods for services. These periods need to be created in the following way based on a provided start date and end date
If start date is not the start of a week, a record must be inserted
from the Start date until the end of the week containing the start
date.
The next record to be inserted will be the start of the week after the start date up until the end date of the last full date prior to the end date (it can be up until the end date, if the end date is a last day of the week.
There is also a requirement to add individual records for bank holidays
The table is currently populated using recursive stored procedures,but has been failing recently due to exceeding the max nest level for SP', functions etc.
I want to remove this issue and I have no issues creating the table where there are no bank holidays, but I am having problems dealing with the bank holiday insertion and update of previous rates entered.
For example take the following
Start Date: 5th Jan 2017
End Date: 8th April 2017
Last Day of Week: Sunday
Bank Holidays: Mar 9th and Apr 6th
The returned records should be
5th Jan - 8th Jan (5th is not a Monday)
9th Jan - 5th Mar (End week prior to Bank Holiday)
6th Mar - 8th Mar (part week due to Bank Holiday)
9th Mar - 9th Mar (Bank Holiday)
10th Mar - 12th Mar (Part week due to Bank Holiday)
13th Mar - 2nd Apr (Full weeks)
3rd Apr - 5th Apr (Part week due to Bank Holiday)
6th Apr - 6th Apr (Bank Holiday)
7th Apr - 8th Apr (End of Period)
I have looked into using recursive CTE's to do this but I am having issues with this.
Any ideas on the best way to implement the above?

Related

Weeks rolling up to months in SQL (date_trunc)

I am working on a MODE Case Study which can be accessed here https://mode.com/sql-tutorial/a-drop-in-user-engagement/#the-problem.
I am trying to access Table 2: Events which has a date column 'occurred_at'. I wanted to check the time frame of this case study, that is weeks and months.
I wrote a simple query
select distinct(date_trunc('week', occurred_at)) as week, date_trunc('month', occurred_at) as month
from tutorial.yammer_events
where event_type = 'engagement'
order by week;
and to my surprise, the first week of '2014-04-28' showed the month 'May' instead of 'April.
Can someone please tell me what is the reason for this?
Thank you
The PostgreSQL date_trunc rolls up the date to the first instance of the date depending upon the granularity (day, week, month, etc.)
For month this instance is the first day of month i.e. Day 1.
For week this instance is the first day of week i.e. Monday.
Suppose the date is 4th July 2021 which is Sunday, then the date_trunc will result in 1st July 2021 for month and 28th June 2021 for week which is Monday inside that week.
Suppose the date is 5th July 2021 which is Monday itself, then the date_trunc will still result in 1st July 2021 for month but result in 5th July 2021 for week since it is already Monday.

MS Access 2010: combining consecutive date ranges

At work, I've been designing an MS Access query to manipulate client service agreements.
The requirement I'm stuck on is that if a client has had multiple consecutive agreements (i.e. the start date of one is the day after the end date of the previous one), they're counted as one (so the earliest start date is used).
The relevant fields in the table are:
Agr_ID (Agreement ID), number
Per_ID (Person ID), text
Agr_Type (Agreement Type), text
Start_Date, date
End_Date, date
For example:
103, A1234, Homecare, 20th Oct 2013, 05th Nov 2013
110, A1234, OT Equip, 06th Nov 2013, 09th Dec 2013
114, A1234, Homecare, 10th Dec 2013, 19th Jan 2014
125, A1234, Homecare, 20th Jan 2014, 15th Jun 2014
147, A1234, Homecare, 16th Jun 2014, null
The last three would be considered a single agreement (spanning the date range 10th Dec 2013 to present) but the top two wouldn't (103 isn't consecutive with 114, 110 is of a different type). The latest agreement is to be used as the base, as subsequent queries will only keep those combined agreements whose end date is later than [Prompt] and which have been open for at least 365 days. So unfortunately, grabbing min(Start_Date) won't do.
So the desired result for that extract would be:
103, A1234, Homecare, 20th Oct 2013, 05th Nov 2013
110, A1234, OT Equip, 06th Nov 2013, 09th Dec 2013
147, A1234, Homecare, 10th Dec 2013, null
I'm thinking several derived tables / subqueries may be needed, to list the agreements for each client, then iteratively work backwards through the resulting table to find the earliest qualifying start date. The only consolation to the amount of recursion involved is that the table I'm basing the query on was created via a MakeTable query that filtered the raw Agreements table, so only agreements with an end date greater than [Prompt] - 365 days or null are included, and the Agreements table this is running off is under 10,000 records.

Getting the last month date's data in sql

I have the below query to get the last month date's data. Suppose if today is 23rd Dec, then it fetches 23rd Nov data. But when it's 31st Dec, then there would be no 31st Nov. In that case it should fetch 30th Nov data.
So, I want to decrease one day and check the condition again and should fetch the data. In this scenario, suppose on March 31st, first that query even should check for feb 31st, then it should check for feb 30, then 29th and so on until the valid date of that particular month.
My current query:
select *
from dataTable
where date(datecolumn)=date(add_months(DATE(sysdate-1) ,-1));
So, this only fetches last month's date data. So, can someone please suggest me how to check for the mentioned validation in the query and fetch the data?
try this:
SELECT dateadd(mm, -1, Convert(Datetime, '2013-12-31')

Previous Year's End Value

I'm trying to retrieve the previous year's end value of a measure.
I know this code gets the value of the previous year, but at the same point in time during that year (so Mar 2012 looks to Mar 2011).
([Measures].[MeasureName], ParallelPeriod([Time].[Calendar].[Year]))
I'd like any date in 2012 to look at the last value in 2011 (Dec 2011). So if we're looking at the Year level of 2012 or any Month level, it all points to Dec 2011.
where are you trying to do this? On a MDX query? Or on a KPI?
Like you can access the value of Dec 2011 like this for example:
ParallelPeriod([Time].[Calendar].[Year], 1, [Time].[Calendar].[Year].[December 2012])
Combine the time functions:
ClosingPeriod([Time].[Calendar].[Month], Ancestor(ParallelPeriod([Time].[Calendar].[Year], 1), [Time].[Calendar].[Year]) )

When was this clock bought?

The clock on the gym wall also shows the day name and the day of the month. This morning it showed Tuesday - 23.
The day obviously rotates through a cycle of 7 - and showed "Tuesday" correctly. The day of the month, though, presumably rotates through a cycle of 31 and showed "23" incorrectly - today is the 1st December (ie. not the 31st November). So this error has been slowly accruing over time.
Given the assumption that no-one has ever reset the clock, what's the most elegant, quick, optimised way of suggesting some of the possible dates for when this clock was bought brand new.
(Bonus credit for showing when the clock will again show the correct day/number combination.)
01-Oct-17 is when the clock will again show the correct day/number combination.
The day of the week (i.e. Tuesday, ... etc) will always be correct, so it is irrelevant to your problem.
Assuming non leap year, you can build a table of 12 rows (1 per month) containing the number of days in this month minus 31.
Jan 0
Feb -3
Mar 0
Apr -1
May 0
Jun -1
Jul 0
Aug 0
Sep -1
Oct 0
Nov -1
Dec 0
You can build a table of the displayed date for every 1st of the month, by adding to the day of the previous month the related number in this list. If the number is negative or equal to zero, add 31 to the figure.
i.e. from the 1st Dec 09 (date at which the clock is displaying 23), you can go to the 1st Jan 10.
You look at this table and find the figure next to Dec, it is 0.
Add 0 to 23 and you know that on the 1st Jan 10, the clock will be displaying 23.
From the 1st Jan 09, you know that the date which will be displayed on the 1st Feb 10 is 23.
From the 1st Feb 10, you can compute the value for the 01 Mar 10, it is 23 + (-3) = 20.
... etc
So, now, at every start of month where you get a value of 1 in this table, you know that the dates in this month will be correct.
If you have to include leap year, you need a second table with the values for a leap year or make an exception for February.
If you want to use this computation for previous dates, substract the figure from the table and when the number you obtain is over 31, just substract 31 to get the day number.
Using these tables and taking in account leap years.
The last past date at which the clock was correct was the 30 September 08 (it was correct between the 01-Jul-08 and the 30-Sep-08)
The next date at which it will be correct will be the: 01-Oct-17 and it will still be correct on the 30-Nov-17.
Now = 1 Dec 2009.
1st day of the month minus 23rd of past month = 8 days (assuming 31 day month).
Moving back counting non-31-days month...
Nov, Sep, June, Apr, Feb (X3), Nov = 8 days offset
So it was bought before Nov 2008?
I didn't code a single line for it, so pardon me if the answer is way off.
In Excel, you can test any date in A2 to see whether the clock will be correct on that date, with the formula =MOD(A2+19,31)+1=DAY(A2)