Last 5 weeks prior to the last week in SQL - 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.

Related

How to find the date of the same day ( same week ) for the previous year ? ( 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

How to pull the past two years of data, but not the data in the current month in SQL

I am trying to pull the data from the past two years, starting from the the past month (not taking into account the current month).
So it will pull all 2 years of data starting from 09/30/2021.
I've tried the following, but the months after September for 2020 get taken out:
WHERE YEAR(ACCDAT_0) >= (YEAR(GETDATE()) -2) AND MONTH(ACCDAT_0) < MONTH(dateadd(dd, -1, GetDate()))
DECLARE #d date = GETDATE();
SET #d = DATEFROMPARTS(YEAR(#d), MONTH(#d), 1);
SELECT ... WHERE ACCDAT_0 >= DATEADD(YEAR, -2, #d)
AND ACCDAT_0 < #d;
Several helpful date articles here, including why you want range queries and not things like YEAR(column): Dating Responsibly
You may try the following logic:
SELECT *
FROM yourTable
WHERE ACCDAT_0 >= DATEADD(year, -2, DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)) AND
ACCDAT_0 < DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0);

Using DATEADD and DATEDIFF truncates the time

I am using the following to get to get the 1st day of next month with time:
select DATEADD(m, DATEDIFF(m, -1, getdate()), 0)
But the output is:
2018-12-01 00:00:00.000
And the expected result is:
2018-12-01 11:53:30.677
I have tried various approaches but not able to get required output. I am using SQL Server 2008.
You can add two datetime values, one for the date and the other for the time:
select DATEADD(month, DATEDIFF(month, -1, getdate()), 0) + cast(cast(getdate() as time) as datetime)
I am guessing that you want the time value from the current time.
Subtract DAY(#date) - 1 days from #date to get first day of that month including time. Then add one month:
SELECT DATEADD(MONTH, 1, DATEADD(DAY, -DAY(GETDATE()) + 1, GETDATE()))
-- 2018-12-01 04:52:33.403
try like below
select DATEADD(m, DATEDIFF(m, -1, getdate()), 0)+ convert(DATETIME,'11:53:30.677')
in case of current time it would be like below
select DATEADD(m, DATEDIFF(m, -1, getdate()), 0)+ convert(datetime, convert(time,getdate()))

T-SQL to get dates

I've SSRS sales report to which I need to pass the dates for previous month's start date and end date which I am able to pass using below code. However, since the sales report has data from the past year(2014) I need to pass the dates for last year as well. The below code gives StartDate1 as 2015-02-01 and EndDate1 as 2015-02-28. I need to get the dates for past year like 2014-02-01 as StartDate2 and 2014-02-28 as EndDate2
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000201', GETDATE()), '19000101') AS StartDate1,
DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '18991231') AS EndDate1
Since last day of month can vary, the important thing is to get the first day of the current month this year. From that you can calculate the other three values.
You could do this easily with expressions in the parameters' default values instead.
Start of Month
=Today.AddDays(1-Today.Day)
End of Month
=Today.AddDays(1-Today.Day).AddMonths(1).AddDays(-1)
Start of Month Last Year
=Today.AddDays(1-Today.Day).AddYears(-1)
End of Month Last Year:
=Today.AddDays(1-Today.Day).AddYears(-1).AddMonths(1).AddDays(-1)
But if you really want to do it in SQL, you can. Note below I'm describing how to get the start of month and then just using placeholder variables for it in the other expressions for clarity.
--Start of Month
dateadd(month, datediff(month, 0, getdate()), 0)
--End of Month
dateadd(day, -1, dateadd(month, 1, #StartOfMonth))
--Start of Month Last Year
dateadd(year, -1, #StartOfMonth)
--End of Month Last Year
dateadd(day, -1, dateadd(month, 1, #StartOfMonthLastYear))
Those are the pieces. Put them together into one giant, very hard to read select statement like so:
select
dateadd(month, datediff(month, 0, getdate()), 0) StartDate1,
dateadd(day, -1, dateadd(month, 1, dateadd(month, datediff(month, 0, getdate()), 0))) EndDate1,
dateadd(year, -1, dateadd(month, datediff(month, 0, getdate()), 0)) StartDate2,
dateadd(day, -1, dateadd(month, 1, dateadd(year, -1, dateadd(month, datediff(month, 0, getdate()), 0)))) EndDate2
Now you see why I recommend just using internal parameters that can leverage the .NET datetime class methods.

Conditional where statement: select different time period when query date varies

I have a query need to select different time period. The logic is:
if today is Tuesday, select Saturday 00:00:00 ~ Monday 23:99;
if today is other weekdays, select the previous working day (00:00:00 ~ 23:99).
Here is the query I have:
Select *
From ...
WHERE
(DATENAME(DW,GETDATE())= 'Tuesday'
AND (<#SalesDate> BETWEEN DATEADD(DAY, -3, GETDATE()) and DATEADD(DAY, -1, GETDATE())))
OR
(DATENAME(DW,GETDATE())<> 'Tuesday'
AND (<#SalesDate> BETWEEN DATEADD(DAY, -1, GETDATE())and DATEADD(DAY, -1, GETDATE())))
It didn't return the result that I want. Anyone can help me? thank you.
BETWEEN is a bit finicky when it comes to date datatypes. See this question.
GETDATE() will return the time for today. You need to strips it off.
-- Today's date, stripped of time
DECLARE #Today datetime = CONVERT(datetime,CONVERT(date,GETDATE()))
Select *
From ...
WHERE
(DATENAME(DW,GETDATE())= 'Tuesday'
AND (#SalesDate >= DATEADD(DAY, -3, #Today) and #SalesDate < DATEADD(DAY, -1, #Today)))
OR
(DATENAME(DW,GETDATE())<> 'Tuesday'
AND (#SalesDate >= DATEADD(DAY, -1, #Today) and #SalesDate < DATEADD(DAY, -1, #Today)))