How to find the date of the same day ( same week ) for the previous year ? ( SQL) - sql

I have a table that contains dates , For each date I need to return a reference date: same day of the same number of the week but during the previous year.
For example let's suppose today is 03-03-2023 , the day is friday and the number of the week is 5 I want as a resulat the date of friday in 2022 during the week number 5.
I have tried this formula but it didn't give me a good result
SELECT DATEADD(day, (DATEPART(week, #now) * 7 + DATEPART(weekday, #now)) - (DATEPART(week, DATEADD(year, -1, #now)) * 7 + DATEPART(weekday, DATEADD(year, -1, #now))), DATEADD(year, -1, #now))
enter image description here
Any help will be appreciated.
Best regards,

Try this:
SELECT DATEADD(WEEK, -52, CAST(GETDATE() AS DATE))

If you can use the ISO weeks definition, you can try the following.
CASE
WHEN YEAR(DATEADD(week, -52, #Date)) = YEAR(#Date)
THEN DATEADD(week, -52, #Date)
ELSE DATEADD(week, -53, #Date)
END
For about 80% of the cases, the -52 calculation will yield the correct result, otherwise (with one exception noted below) -53 gives the correct answer.
The only exceptional case is when the reference date is in ISO week 53 and the prior year only has 52 weeks. in that case, it will end up in week 52 of the prior year, which may be a reasonable accommodation.
If you wish to use a different week definition I believe the above can be adapted to week instead of iso_week and possibly use SET DATEFIRST to adjust the week boundaries.
If you don't care about ISO weeks or any other week-numbering scheme, and just want to get the closest date one year-ago on having the same day-of-week, then Nayanish's posted is the simple answer. If you also want to always guarantee that year is offset by 1, then the following adjustment can be made:
CASE
WHEN DATEPART(year, DATEADD(week, -52, #Date)) < DATEPART(year, #Date)
THEN DATEADD(week, -52, #Date)
ELSE DATEADD(week, -53, #Date)
END

Related

How to extract 'Week Number' and 'Day Number' from Date if Start Day is 'Monday' in a Month SQL

I am extracting below from a date:
Week Number
Day Number
Where start day of my Week is Monday.
For Example the date is : '1st May 2019' or '2019-05-01'
Then
Week Number = 1
Day Number = 3
Because the day is Wednesday on 1st May 2019.
I am using MS SQL Server 2012.
and used below code from net to get Week Number.
I get the Week Number from this but i do not understand what actually it is doing.
select datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, #date), 0)), 0), #date - 1) + 1
Can anyone explain it to me and tell me how to extract the Day Number.
This select will give you the #date day of week (1: Monday, 7: Sunday), regardless of your ##DATEFIRST set MS Doc:
select (DATEPART(DW, #date) + ##DATEFIRST + 5) % 7 + 1 as [Day of Week]
If you set datefirst, you can simply do:
set datefirst 1; -- "1" = "Monday"
select datepart(week, getdate()), datepart(weekday, getdate())
Others have mentioned how to get the day-of-week.
In terms of your code for getting week-of-month:
select datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, #date), 0)), 0), #date - 1) + 1
To my eye it appears to get the number of full months elapsed between day zero and the current date, giving us a month-serial.
Then adds zero months to this figure (which is apparently being used to cast the month-serial back to a date representing the beginning of the current month), giving us a beginning-of-month date.
It then gets the number of full weeks elapsed between day zero and the beginning-of-month date, giving us a week-serial.
The week-serial is then cast back to a date representing the beginning-of-week date, representing the Monday on or prior to the beginning-of-month date.
It then gets the difference, in weeks, between the monday-on-or-prior date and the day before the current date, and adds 1 (so that the first week of the month is represented as Week 1).
It sounds like a plausible algorithm, but I wouldn't endorse it without testing and inspecting the intermediary values, however, or unless you have found it from an authoritative source.
Check This-
SELECT ISNULL(NULLIF(DATEPART(DW,GETDATE())-1,0),7)
I have constructed the query as per your need. It works fine.
NOTE : Sunday is considered as 1st day of the week and Saturday is considered as 7th day of the week
DECLARE #dt datetime='2019-05-01'
DECLARE #Weekday INT
if(((DATEPART(DW, #dt) + ##DATEFIRST + 5) % 7 +2) =8)
SET #Weekday =1
else
SET #Weekday = ((DATEPART(DW, #dt) + ##DATEFIRST + 5) % 7 +2)
select DATEPART(week, #dt)- DATEPART(week, CONVERT(CHAR(6), #dt, 112)+'01')+ 1 AS [Week Number], #Weekday AS [Day of Week]

Last 5 weeks prior to the last week in SQL

I want to take the last 5 weeks prior to the week before the current week. Today is Oct 4, 2017 so I want date range to be between Aug 21-Sep 24. This is the code I'm using, but it doesn't work for some reason:
DATEADD(week, -5, GETDATE()) and DATEADD(week, -1, GETDATE())
I also tried DATEADD(week, -6, GETDATE()) and DATEADD(week, -2, GETDATE()) but no change happens, so weird.
Can anyone help me please. It's sql query in SQL 2012.
WHERE hire_date between DATEADD(week, -6, GETDATE()) and DATEADD(week, -2, GETDATE())
Look at each of the expressions individually. Use Management Studio (or similar) to run just this:
SELECT DATEADD(week, -1, GETDATE())
And you'll see something like this (relative to the time when you run it):
2017-09-27 15:05:39.453
That's exactly one week ago, which was still a Wednesday. You want Sunday, the start of that week. So now do this:
SELECT DATEADD(week, DATEDIFF(week, 0, GETDATE()) -1, 0)
Which gives you this result:
2017-09-25 00:00:00.000
Closer. It works by taking day 0 and adding one less than the number of weeks that have passed since the week from your target date. You're adding whole weeks, and so you end up with a predictable whole-week start. You get the 25th (Monday) instead of the 24th because day 0 (Jan 1 1900) happened to be a Monday. But it's reliably a Monday, and easy enough now to account for the one more day:
SELECT DATEADD(DAY, -1, DATEADD(week, DATEDIFF(week, 0, GETDATE()) -1, 0))
And now we have a date you can use, from an expression that will consistently get it right:
2017-09-24 00:00:00.000
Sort of. You do need to carefully test how this behaves if run on Sunday or Monday, especially as Sql Server has a configurable start-of-week value. You may find you've crossed one fewer or greater week boundaries than you expect and end up with weird off-by-one errors. But even if that happens, this approach puts you on the path you need to walk.
For the other end, just change the number of weeks:
SELECT DATEADD(week, DATEDIFF(week, 0, GETDATE()) -6, 0)
To get this:
2017-08-21 00:00:00.000
Since the question asked for the Monday instead of Sunday we get skip the extra DATEADD() from before.
Now put it all together like so:
WHERE hire_date between
DATEADD(week, DATEDIFF(week, 0, GETDATE()) -6, 0)
AND
DATEADD(DAY, -1, DATEADD(week, DATEDIFF(week, 0, GETDATE()) -1, 0))
From what you're saying I think you need the first day of the earliest week to the last day of the latest week. To achieve this, you can do this:
WHERE hire_date between DATEADD(week, -6, DATEADD(WEEK, DATEDIFF(wk,0,GETDATE()), 0))
and DATEADD(week, -2, DATEADD(WEEK, DATEDIFF(wk,5,GETDATE()), 6))
DATEADD(week, -5, GETDATE()) substracts 30 days. You are going to have to do some manual DATEADD to get it to the beginning of the week, which is what it sounds like you're trying to do.
DECLARE #date datetime = GETDATE()
DECLARE #dw nvarchar = DATENAME(dw, #date)
IF #dw = 'Monday' SET #date = DATEADD(day, -1, #date)
ELSE IF #dw = 'Tuesday' SET #date = DATEADD(day, -2, #date)
....
WHERE hire_date between DATEADD(week, -6, #date) and DATEADD(week, -2, #date)
This way, you can set the beginning of the week yourself without having to be dependent on system culture.

How to filter my results so it shows the last four months of data - sql

I'm trying to create a stored procedure that gets the last 4 months worth of results from the below query but I'm unsure how to do this.
This is what I have done so far:
Declare #Number varchar(30) = '12'
Select
month = month(EndDate),
YEAR = YEAR(EndDate),
SUM(DownloadUnits) as downloads,
SUM(UploadUnits) as uploads,
number
from testTable
where number=#Number
GROUP BY MONTH(EndDate), Year(Enddate),number
How can I filter it out so that when I pass month parameter (I haven't created it yet) it filters out the results so it only shows the last four months? (I have hard coded the number parameter for testing)
The last N months from now meet the condition
where EndDate >= dateadd(month, -#DEDUCT_MONTHS, cast(getdate() as DATE))
Removing the cast will enforce the current time as a constraint as opposed to midnight N months ago.
If you need to get whole months then you will need to get the first of the month 4 months ago.
You can get the first of the current month using:
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101');
Adapting this slightly will give you the first of the month 4 months ago:
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - 4, '19000101');
Then you can just apply this filter to your query:
WHERE EndDate >= DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - 4, '19000101')
Or if you need to pass the number of months a parameter (it should be an INT not a varchar by the way):
WHERE EndDate >= DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - #Number, '19000101')
If you pass a date parameter, just replace GETDATE() with your parameter name.
DECLARE #StartDate date
SET #StartDate=Dateadd(Month, Datediff(Month, 0, DATEADD(m, -6, getdate())), 0)
--first day of the month, (current month-6 month)
The script above will return with the first day of the month - 6 month ago .
This solution is from stackoverflow somewhere, unfortunately I dont seem to find the original post.. :(
To understand how it works try to reverse-engineer as per follows:
DECLARE #StartDate1 date
SET #StartDate1= DATEADD(m, -6, getdate())
PRINT #Startdate1
DECLARE #StartDate2 int
SET #StartDate2= Datediff(Month, 0, DATEADD(m, -6, getdate()))
PRINT #Startdate2
DECLARE #StartDate3 date
SET #StartDate3=Dateadd(Month, 1369, 0)
PRINT #Startdate3

Get records from the week until the given date

How can i get records in SQL Server 2005. Input will be a weekday Date. Output should be all the records from that week before that date. For Example, If i give a Wednesday Date, i should get all the records from Monday until Wednesday of that week.
I have tried this to get all the records in a specific week when a weekday is given as input. But i want records until the given day from Monday.
where RD.Date > DATEADD(dd, -(DATEPART(dw, #Date)-1), #Date) and RD.Date < DATEADD(dd, 7-(DATEPART(dw, #Date)), #Date)
Thanks for the help in advance!!
How about this?
WHERE RD.Date BETWEEN DATEADD(wk, DATEDIFF(wk,0,#Date), 0) AND #Date
I know in SQL Server, BETWEEN forces an inclusive search, so you can do a > and < against RD.DATE
This should work:
SET DATEFIRST 1
...
WHERE RD.Date >= DATEADD(dd, (-1) * (DATEPART(dw, #Date) - 1), #Date)
AND RD.Date < DATEADD(dd, 1, #Date) -- inclusive
DATEPART(dw, #Date) returns the day-number in the week, so for wednesday it returns 3. But since you want to include the monday i needed to subtract 1.
MSDN according to the comment of Lamak:
When datepart is week (wk, ww) or weekday (dw), the return value
depends on the value that is set by using SET DATEFIRST.

SQL Date Function

I may be using the wrong term (hence why I can't find it on google).
"Are there any functions or common code for Accounting Months Deliminations?"
For Example, this month started on a friday but on most accounting journals the weeks are measured by the first monday of the month so instead of having the 1st of July it would be the 4th of July. Same thing with the month end (29th instead of the 31st)
Again, I'm sure someone has created this 'wheel' before, and I can't seem to find it for the life of me.
The following query assumes a table, SalesTable, has a field called Amount (the value you want to sum) and a field called SaleDate (the date on which the sale occured.) It also assumes that accounting months begin the first Monday of the month and end on the Sunday prior to the beginning of the next accounting month.
Again, I highly recommend a table-based approach to this, but if you can't modify the schema, this should do the trick in T-SQL:
SELECT
CASE WHEN s.SaleDate < DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
THEN DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, DATEADD(day,-7,s.SaleDate) ),DATEADD(day,-7,s.SaleDate) )), 0)
ELSE DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
END AccountingMonth,
SUM(s.Amount) TotalSales
FROM SalesTable s
GROUP BY
CASE WHEN s.SaleDate < DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
THEN DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, DATEADD(day,-7,s.SaleDate) ),DATEADD(day,-7,s.SaleDate) )), 0)
ELSE DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
END
Note that the AccountingMonth return field actually contains the date of the first Monday of the month. In actual practice, you probably want to wrap this entire query in another query that reformats AccountingMonth to whatever you like... "2011-07", "2011-08", etc.
Here's how it works: This bit of code is the important part:
DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
It takes any date and returns the first Monday of the month in which that date occurred. In your case, however, you have to do a little more work because a sale might have occurred in the window between the first of the month and the first Monday of the month. The CASE statement detects that scenario and, if it's true, subtracts a week off of the date before calculating the first Monday.
Good luck!
-Michael
I have some code that takes in a year and month and returns the fiscal start and end dates. Perhaps this will give you something to go by:
DECLARE #yr int;
DECLARE #mo int;
SELECT #yr = 2011
SELECT #mo = 7
DECLARE #FiscalMonthStartDate datetime
DECLARE #FiscalMonthEndDate datetime
DECLARE #startOfMonth datetime
DECLARE #startOfNextMonth datetime
select #startOfMonth = CAST((CAST(#yr AS VARCHAR(4)) + '-' + CAST(#mo AS VARCHAR(2)) + '-' + '01') as DATE)
select #startOfNextMonth = CAST((CAST(#yr AS VARCHAR(4)) + '-' + CAST((#mo + 1) AS VARCHAR(2)) + '-' + '01') as DATE)
SELECT #FiscalMonthStartDate =
CASE
WHEN DATEPART(DW,#startOfMonth) = 0
THEN DATEADD(DD, 1, #startOfMonth)
ELSE
DATEADD(DD, 8 - DATEPART(DW,#startOfMonth), #startOfMonth)
END
SELECT #FiscalMonthEndDate =
CASE
WHEN DATEPART(DW,#startOfNextMonth) = 0
THEN DATEADD(DD, 1, #startOfNextMonth)
ELSE
DATEADD(DD, 8 - DATEPART(DW,#startOfNextMonth), #startOfNextMonth)
END
-- subtract one day to get end of fiscal month (not start of next fiscal month)
SELECT #FiscalMonthEndDate = DATEADD(DD, -1, #FiscalMonthEndDate)
SELECT #FiscalMonthStartDate, #FiscalMonthEndDate