Write SQL Code to automate the changing of the parameter year and period - sql

If the day of the current date = 14 then the values of the parameter need to change.
The month and possibly year will need to advance by 1
- May need to consider that on the 14th day of the month there may be a technical problem that prevents this process from running.
Example Friday is the 14th when the sql script is run on the sql server and sees that its the 14th then the field prmstring needs to be updated from 201305 to 201306.

SET #start = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()-13), 0)
SET #stop = DATEADD(MONTH, 1, #start)
The -13 moves everything back 13 days.
- The 1st to 13th of each month, are moved to a date in the previous month
- The 14th onwards of each month, stay in the same month
The DATEADD(DATEDIFF()) rounds the date down to the beginning of the month.
In this way the 1st to 13th of every month are rounded down to the 1st of the previous month. And the 14th onwards are rounded down to the 1st of the current month.
The end date is then simply the value calculated above, plus 1 month.

How about this?
select
substring(
convert(
varchar(10),
dateadd(mm, 1, dateadd(mm, datediff(mm, 0, dateadd(d,-13,getdate())), 0))
,112)
,1,6) as newDate

this is what worked
DECLARE #curentday VARCHAR(2)
select #curentday =datepart(day,getdate())
declare #yearmonth varchar (6)
select #yearmonth =convert(varchar,getdate(),112)
If #curentday in (14,15,16)
begin
if (select prmString11 from FC_App where prmName1='prmCurFCPrd') <> #yearmonth
begin
update FC_App
set prmString11 = #yearmonth
where prmName1='prmCurFCPrd'
update FC_App
set prmString11 = CONVERT(VARCHAR(6),DATEADD(dd,1-day((DATEADD(mm,-1,GETDATE()))),DATEADD(mm,- 1,GETDATE())),112)
where prmName1='prmcurWIPPrd'
End
end

Related

Converting dates to periods - last saturday of each month sql

Not a strong SQL user by any means. I'm trying to run a script that will return the fiscal period given the date of the transaction. The fiscal period is up to the last saturday of each month.
So for the year 2022, period 1 January would be Jan 1, 2022 to Jan 29,2022 (last saturday) and Feb would be Jan 30th to Feb 26, 2022 (last saturday). I need to run this script for multiple years.
Give this a go, is it for MSSQL but would be pretty easy to flip around for many other DBMS. Just that each is a little tricky with their own date/time syntax. That being said the general concept should work for just about any of them as I'm not using anything unique to MSSQL.
DECLARE #DATE datetime
DECLARE #EOM datetime
DECLARE #SAT datetime
-- set a date to use
SET #DATE = '2022-06-28'
-- add a month
SET #EOM = DATEADD(mm, 1, #DATE)
-- subtract the days to get last day of month
SET #EOM = DATEADD(dd, -DAY(#EOM), #EOM)
-- subtract days using weekday number to get Saturday
SET #SAT = DATEADD(dd, -(DATEPART(dw, #EOM))-1, #EOM)
-- display the result
SELECT #EOM as [EOM]
, DATENAME(dw, #EOM) as [EOM_Day]
, #SAT as [Last_Sat]
, DATENAME(dw, #SAT) as [Last_day]
Although in my experience I would use this to create a calendar table of sorts. It can be hard to use a function like this to JOIN to, etc. But if you have the dates and results all stored out for the next 10 (or more) years it makes it much easier to use.

SQL query that displays the current date and count of days between two specific dates

I am trying to write a SQL query that shows the count of the days and date depending upon the financial period it falls in. The financial period starts 5 days before the month end eg march 27th to 26th April
For the above mentioned period if the day is 29th march, the count of the day should be 3 and the date should be 2020-04. The date should adjust depending upon the period it falls in.
I tried to adress the second part of this query by writing the below script but it does not bring any result
declare #date datetime
set #date = getdate()
SELECT format (date,'yyyy-MM-dd') as date
where #date
between dateadd(day,-5,EOMONTH(getdate(),-1)) and dateadd(day,-5,EOMONTH(getdate()))
updated to include 5 days from previous month.
Is this what you are looking for the second part?
Edit: Modifying the query. I guess this should give you what you need for both the parts.
you can try changing the dates in set #date.
Please note that the -4 instead of -5 is done intentionally as you said the financial month starts 5 days earlier. For March, 31 - 5 would give 26, but it should start on 27 right? so that on 29th the no. of days should be 3 including 27 and 29. Anyways, the query should be self explanatory, might just need to change the number depending on your requirement.
declare #date datetime
--set #date = getdate()
set #date = '2020-02-14'
SELECT format(#date,'yyyy-MM-dd') as date,
case WHEN #date < dateadd(day,-4,EOMONTH(#date)) THEN format(EOMONTH(#date),'yyyy-MM')
ELSE format(EOMONTH(#date, 1),'yyyy-MM') END
AS FinancialMonth,
CASE WHEN #date < dateadd(day,-4,EOMONTH(#date)) THEN DATEDIFF(day,dateadd(day,-5,EOMONTH(#date,-1)), #date)
ELSE DATEDIFF(day, dateadd(day,-5,EOMONTH(#date)), #date) END
AS CountDays
The following code will calculate what you need. Please read the comments in the code itself.
-- First, lets declare all the variables we need.
-- I tried to name them so they are selfexplanatory.
declare #inputdate DateTime,
#financialPeriodStartDate DateTime,
#EndOfTheMonth DateTime,
#nextFinantialMonthYear DateTime,
#previousFinancialPeriodStartDate DateTime
-- Now we calculate some of the values
set #inputdate = GETDATE() -- Let's use Today's date, but you can change this to any date.
set #EndOfTheMonth = EOMONTH(#inputdate) -- This is the end of the month for the input date
set #financialPeriodStartDate = DATEADD(DAY,-5,EOMONTH(#inputdate)) -- This is you Financial Period Start Date for the giving input date.
set #previousFinancialPeriodStartDate = DATEADD(DAY,-5,EOMONTH(DATEADD(MONTH, -1, #inputdate))) -- Also calculates the Start Date of the precious financial period.
set #nextFinantialMonthYear = DATEADD(MONTH, 1,#financialPeriodStartDate) -- This is the start date of the next financial period.
-- In the following Select, it calculates the values you need, based in the previous variables.
select
#inputdate as Today,
#EndOfTheMonth as EndOfMonth,
#previousFinancialPeriodStartDate as PreviousFinancialPeriodStartDate,
#financialPeriodStartDate as FinacialPeriodStartDate,
CASE WHEN DATEDIFF(DAY , #financialPeriodStartDate, #inputdate + 1 ) < 0
THEN DATEDIFF(DAY , #previousFinancialPeriodStartDate, #inputdate + 1 )
WHEN DATEDIFF(DAY , #financialPeriodStartDate, #inputdate + 1 ) >=0
THEN DATEDIFF(DAY , #financialPeriodStartDate, #inputdate + 1 )
END as DaysFromFPStartDate,
STR(YEAR(#nextFinantialMonthYear)) +'-'+LTRIM(RTRIM(STR(MONTH(#nextFinantialMonthYear)))) as NextFinantialPeriodMonthAndYear
I hope it helps.

Two Predefined Dates

If I want to search records based on the previous month's stats how would I do that? So, if I want a report on June 15th, it would include May 15-June 14. A report for July 15th would include June 15-July 14 and so on. As of now I have this:
where currentemploydate between CAST('2013/05/15' AS DATETIME) AND CAST('2013/06/14' AS DATETIME)
but then I don't know how to auto update the dates for next month. If the report is ran on the 20th, it still shows the dates from the 14th of the current month back to the 15th of the previous month
Then I think you want:
where currentemploydate between CAST('2013-05-15' AS DATETIME) AND
dateadd(month, 1, CAST('2013-05-15' AS DATETIME) )
This should work for any date constant.
DECLARE #START datetime
SET #START = '2012-07-31'
DECLARE #END datetime
SET #END = DATEADD(DAY, 30, #START)
select #START, #END
Assuming a month is 30 days though....is that an acceptable assumption?

Find the next occurance of a day of the week in SQL

I'm trying to update a SQL report sproc's WHERE clause to check whether a given date falls on or before the next occurrence of a class. Classes have a StartDate and occur once per week on the same day each week. Given the StartDate, how can I find the next occurrence of that day of the week?
E.G. If the StartDate is 1/18/2012, a Wednesday, and I run the report as of today, 1/26/2012, I need to find 2/1/2012 which is the next Wednesday after 1/26. If the StartDate is 1/19, a Thurs, and I run the report today, the formula should give me Thurs 1/26 which is today.
Here's sort of the idea in SQL:
SELECT *
FROM tbl_Class cs
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID
WHERE ...
AND sce.StartDate < [Find date of next class after #AsOfDate using cs.StartDate]
Here's some example SQL that I came up with. 3 iterations so you can follow how I got to the end. The 3rd iteration should be something you can incorporate into a WHERE clause by substituting your column names for the variables.
Setup:
DECLARE #Startdate DATETIME,#currentdate datetime
SET #Startdate = '1-26-2012'
SET #Currentdate = '1-23-2012'
--This section just normalizes it so you can use 7 as the interval
--The offset depends on your current setting for DATEFIRST, U.S. English default is 7, Sunday.
-- see http://msdn.microsoft.com/en-us/library/ms187766.aspx
DECLARE #StartDateWorkingDayOfWeek int,#CurrentDateWorkingDayOfWeek int
SELECT #StartDateWorkingDayOfWeek =(DATEPART(weekday,#Startdate)-2)
SELECT #CurrentDateWorkingDayOfWeek=(DATEPART(weekday,#Currentdate)-2)
Iteration #1
--Iteration 1
IF #StartDateWorkingDayOfWeek < #CurrentDateWorkingDayOfWeek
SELECT DATEADD(DAY,DATEDIFF(DAY,0,#Currentdate)/7*7 + 7,#StartDateWorkingDayOfWeek)
else
SELECT DATEADD(DAY,DATEDIFF(DAY,0,#Currentdate)/7*7 + 0,#StartDateWorkingDayOfWeek)
Iteration #2
--Iteration 2
SELECT DATEADD(DAY,DATEDIFF(DAY,0,#Currentdate)/7*7 +
CASE WHEN #StartDateWorkingDayOfWeek < #CurrentDateWorkingDayOfWeek
then 7
ELSE 0
end
,#StartDateWorkingDayOfWeek)
Iteration #3
--iteration 3
SELECT DATEADD(DAY,DATEDIFF(DAY,0,#Currentdate)/7*7 +
CASE WHEN (DATEPART(weekday,#Startdate)-2) < (DATEPART(weekday,#Currentdate)-2)
then 7
ELSE 0
end
,(DATEPART(weekday,#Startdate)-2))
Hat tip to this article:
http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3
Here's what I came up with thanks to TetonSig and his reference to this link: http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3
We can get the date of the previous Monday exclusive of the current date (#AsOfDate) like so:
SELECT DATEADD(day, DATEDIFF(day,0, #AsOfDate-1) /7*7, 0);
This gets the number of days between 1/1/1900 and #AsOfDate in days. /7*7 converts that to whole weeks, and then adds it back to 1/1/1900 (a Mon) to get the Monday before #AsOfDate. The -1 makes it exclusive of #AsOfDate. Without the minus 1, if #AsOfDate were on a Monday, it would be counted as the "previous" Monday.
Next the author shows that to get the inclusive next Monday, we simply need to add 7 to the exclusive previous Monday formula:
SELECT DATEADD(d, DATEDIFF(day,0, #AsOfDate-1) /7*7, 0)+7;
Voila! We've now got the first Monday on or after #AsOfDate. The only problem is, the Monday (0) above is a moving target in my case. I need the first [DayOfWeek] determined by the class date, not the first Monday. I need to swap out a ClassDayOfWeek calculation for the 0s above:
DATEADD(d, DATEDIFF(d, [ClassDayOfWeek], #AsOfDate-1)/7*7, [ClassDayOfWeek])+7
I wanted to calculate the ClassDayOfWeek without being dependent on or having to mess with setting ##datefirst. So I calculated it relative to the base date:
DATEDIFF(d, 0, StartDate)%7
This gives 0 for Mon, 6 for Sun so we can now plug that in for [ClassDayOfWeek]. I should point out that this 0-6 value is dates 1/1/1900-1/7/1900 represented as an int.
DATEADD(d, DATEDIFF(d, DATEDIFF(d, 0, StartDate)%7, #AsOfDate-1)/7*7, DATEDIFF(d, 0, StartDate)%7)+7
And in use per the question:
SELECT *
FROM tbl_Class cs
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID
WHERE ...
AND sce.StartDate < DATEADD(d,
DATEDIFF(d,
DATEDIFF(d, 0, cs.StartDate)%7,
#AsOfDate-1)/7*7,
DATEDIFF(d, 0, cs.StartDate)%7)+7
I derived the answer with a simple case statement.
In your situation #targetDOW would be the day of the week of the class.
DECLARE #todayDOW INT = DATEPART(dw, GETDATE());
DECLARE #diff INT = (#targetDOW - #todayDOW);
SELECT
CASE
WHEN #diff = 0 THEN GETDATE()
WHEN #diff > 0 THEN DATEADD(d,#diff,GETDATE())
WHEN #diff < 0 THEN DATEADD(d,#diff + 7,GETDATE())
END;

SQL Server Date Logic - Finding the next reminder date

Given the following database table:
StartDate DATETIME -- day that the reminder period starts
LastReminderDate DATETIME -- the last time the reminder triggered
DayOfMonth INT -- the day of the month to remind the user
Interval INT -- how often in months to remind the user
How can I figure out the next reminder date based on these values? For example:
StartDate = '6/1/2011'
LastReminderDate = '6/5/2011'
DayOfMonth = 5 -- remind on the 5th of the month
Interval = 2 -- remind every other month
For this particular example, the next reminder date should be 8/5/2011 because it reminds on the 5th of the month every two months. How would I write a function to figure this out?
If LastReminderDate is NULL, then LastReminderDate should be equal to StartDate
UPDATE:
StartDate = '6/1/2011'
LastReminderDate = NULL
DayOfMonth = 5
Interval = 2
In this case, there was no last reminder date. The first time the reminder would occur would be 6/5/2011. The solutions below seem to be returning 8/5 in this case.
Here are some specific rules:
The Reminder should always occur on whatever DayOfMonth is. If DayOfMonth would be illegal for the given month then it should be the last day of that month. For example....if DayOfMonth is 31 and the next reminder date would fall on June 31, then it should be June 30th instead.
The next reminder date should always be based off of the Last Reminder Date plus the Interval. If Last Reminder Date does not match the Day of Month, then it could potentially be more than what the interval was. For example...if Last Reminder was 6/1/2011 and the interval is 2 months, but the reminder is for the 20th of the month, then the next reminder will be 8/20/2011.
If there is no last reminder date, then use the Start Date instead of last reminder date...but this will use the earliest date in the future. If start date was 6/1/2011 and day of month is 5, then this will be 7/5/2011 since today is 6/22/2011. If Day of Month was 25 then it would be 6/25/2011
DECLARE
#StartDate AS datetime, -- day that the reminder period starts
#LastReminderDate AS datetime, -- the last time the reminder triggered
#DayOfMonth AS integer, -- the day of the month to remind the user
#Interval AS integer -- how often in months to remind the user
SET #StartDate = '6/1/2011'
SET #LastReminderDate = '6/5/2011'
SET #DayOfMonth = 5 -- remind on the 5th of the month
SET #Interval = 2 -- remind every other month
SELECT
CASE
WHEN #LastReminderDate IS NULL
THEN
CASE WHEN Day(#StartDate) <= #DayOfMonth
THEN DateAdd( month, ((Year( #StartDate ) - 1900) * 12) + Month( #StartDate ) - 1, #DayOfMonth - 1 )
ELSE DateAdd( month, ((Year( #StartDate ) - 1900) * 12) + Month( #StartDate ) - 0, #DayOfMonth - 1 )
END
ELSE DateAdd( month, #Interval, #LastReminderDate )
END
The meat of this is the last four lines, the SELECT CASE ... END statement. I provided a whole script that lets you plug in different values, and see how the SELECT CASE ... END behaves for those test values.
But to just use this on your table, use only the last four lines (and remove the # from the front of the names so they match the table's column names).
You could also generalize this so that Interval doesn't have to be months. If your table had an IntervalType column, you could supply that as the first argument to DateAdd(). See the docs but some common intervals are days, months, years, and so on.
EDIT2: Respect DayOfMonth.
Since you want to use the StartDate if there is no LastReminderDate, then you'll want to use COALESCE for that bit of logic: COALESCE(LastReminderDate, StartDate)
Now, get to the last of the previous month: DATEADD(DAY, -DAY(COALESCE(LastReminderDate, StartDate)), COALESCE(LastReminderDate, StartDate))
Finally, add the months and then get to the date that we need:
DATEADD(MONTH, Interval, DATEADD(DAY, -DAY(COALESCE(LastReminderDate, StartDate)) + DayOfMonth, COALESCE(LastReminderDate, StartDate)))
This will potentially go forward less than two months if the date of the last reminder was on a day of the month after the "DayOfMonth" that's configured for the reminder. You should be able to tweak that depending on what your business logic is in that situation.