Get the date of Sunday and Saturday 2 weeks ago - sql

I have a stored procedure that produces a report each night. This SP references a view that takes a snapshot of data from 2 weeks ago (Sunday to Saturday).
I need to get the dates of the Saturday and Sunday from two weeks ago (so for today that would be 23/24 of December.
I have searched through many solutions but I am unable to find a decent response to this - any one able to help with an answer as well as explaining a little bit of the reason for doing it that way (it seems like there are a thousand ways to do it).
Thanks

Here is the answer in case any one needs it in future.
SELECT DATEADD(wk, -2, DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))

Try this (for Saturday) is the same for Sunday:
DECLARE #today datetime
SET #today = GETDATE()
SELECT
CASE
WHEN DATENAME(weekday, #today) = 'Monday' THEN DATEADD(day, -15, #today)
WHEN DATENAME(weekday, #today) = 'Tuesday' THEN DATEADD(day, -16, #today)
WHEN DATENAME(weekday, #today) = 'Wednesday' THEN DATEADD(day, -17, #today)
WHEN DATENAME(weekday, #today) = 'Thursday' THEN DATEADD(day, -18, #today)
WHEN DATENAME(weekday, #today) = 'Friday' THEN DATEADD(day, -19, #today)
WHEN DATENAME(weekday, #today) = 'Saturday' THEN DATEADD(day, -13, #today)
WHEN DATENAME(weekday, #today) = 'Sunday' THEN DATEADD(day, -14, #today)
END
DATENAME with weekday parameter returns the name of the day, so if you are on Monday you must subtract 15 days to reach Saturday and so on.
Pay attention: If you have another language set you can change it for your query using:
SET LANGUAGE us_english
You can see SqlFiddle

Since the day of week value can differ on different machines you either need to set it using the set datefirst 1 command as suggeste in Podiluska's answer,
or you can do it by first determining the actual value for sunday and add that to the days you are subtracting.
To determine the actual value for sunday simply ask the value for a know sunday, like 2018-01-07 for example
Below example should return 2017-12-23 / 2017-12-24
It will also return this if you are running this on friday, or thursday, or whatever day...
-- this will contain are test date
declare #date date = getdate() - 2
-- determine the number for sunday
declare #Sunday int = (select datepart(dw, '20180107'))
select convert(date,dateadd(d, -15 - datepart(dw, #date) + (datepart(dw, #date) - #Sunday), getdate())),
convert(date,dateadd(d, -14 - datepart(dw, #date) + (datepart(dw, #date) - #Sunday), getdate()))

That depends on how you define when your week starts, but the basic principle is to find the start of this week, and take away 14 days.
eg:
set datefirst 1
select convert(date,dateadd(d, -15-datepart(dw, getdate()), getdate())),
convert(date,dateadd(d, -14-datepart(dw, getdate()), getdate()))

Sorry, I'll work on a general form for these; this is the quick and dirty.
I like the NEXT_DAY function. Simple, and obvious as to what it does.
declare
vFromDate date := trunc( sysdate ) - 9 ; -- '27 Feb 2019'
vSatDate date ;
vSunDate date ;
begin
-- test a range of dates
while vFromDate <= sysdate -- '3 Mar 2019'
loop
select NEXT_DAY ( TRUNC ( vFromDate) - 21, 'SAT') -- 7: general form for these?
-- keep or discard the " - 1" depending on if the 2 wk Sunday is the desired Sunday
, NEXT_DAY ( TRUNC ( vFromDate) - 20 - 1, 'SUN') -- 1:
into vSatDate, vSunDate
from dual ;
dbms_output.put_line( to_char( vFromDate, 'dd Mon": "' )
|| to_char( vSatDate, 'dd Mon' )
|| to_char( vSunDate, '", "dd Mon' )
);
vFromDate := vFromDate + 1 ;
end loop ;
dbms_output.put_line( rpad('*', 21, '*' ) );
end ;

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

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)))

Get last Friday's Date unless today is Friday using T-SQL

I'm trying to get the correct SQL code to obtain last Friday's date. A few days ago, I thought I had my code correct. But just noticed that it's getting last week's Friday date, not the last Friday. The day I'm writing this question is Saturday, 8/11/2012 # 12:23am. In SQL Server, this code is returning Friday, 8/3/2012. However, I want this to return Friday, 8/10/2012 instead. How can I fix this code? Since we're getting to specifics here, if the current day is Friday, then I want to return today's date. So if it were yesterday (8/10/2012) and I ran this code yesterday, then I would want this code to return 8/10/2012, not 8/3/2012.
SELECT DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0))
try this:
declare #date datetime;
set #date='2012-08-09'
SELECT case when datepart(weekday, #date) >5 then
DATEADD(DAY, +4, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0))
else DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0)) end
result:
2012-08-03
Example2:
declare #date datetime;
set #date='2012-08-10'
SELECT case when datepart(weekday, #date) >5 then
DATEADD(DAY, +4, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0))
else DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, 0, #date), 0)) end
result:
2012-08-10
Modular arithmetic is the most direct approach, and order of operations decides how Fridays are treated:
DECLARE #test_date DATETIME = '2012-09-28'
SELECT DATEADD(d,-1-(DATEPART(dw,#test_date) % 7),#test_date) AS Last_Friday
,DATEADD(d,-(DATEPART(dw,#test_date+1) % 7),#test_date) AS This_Friday
Use this :
SELECT DATEADD(day, (DATEDIFF (day, '19800104', CURRENT_TIMESTAMP) / 7) * 7, '19800104') as Last_Friday
None of that? Try this:
DECLARE #D DATE = GETDATE()
SELECT DATEADD(D,-(DATEPART(W,#D)+1)%7,#D)
A tested function which works no matter what ##DATEFIRST is set to.
-- ==============
-- fn_Get_Week_Ending_forDate
-- Author: Shawn C. Teague
-- Create date: 2017
-- Modified date:
-- Description: Returns the Week Ending Date on DayOfWeek for a given stop date
-- Parameters: DayOfWeek varchar(10) i.e. Monday,Tues,Wed,Friday,Sat,Su,1-7
-- DateInWeek DATE
-- ==============
CREATE FUNCTION [dbo].[fn_Get_Week_Ending_forDate] (
#DayOfWeek VARCHAR(10),#DateInWeek DATE)
RETURNS DATE
AS
BEGIN
DECLARE #End_Date DATE
,#DoW TINYINT
SET #DoW = CASE WHEN ISNUMERIC(#DayOfWeek) = 1
THEN CAST(#DayOfWeek AS TINYINT)
WHEN #DayOfWeek like 'Su%' THEN 1
WHEN #DayOfWeek like 'M%' THEN 2
WHEN #DayOfWeek like 'Tu%' THEN 3
WHEN #DayOfWeek like 'W%' THEN 4
WHEN #DayOfWeek like 'Th%' THEN 5
WHEN #DayOfWeek like 'F%' THEN 6
ELSE 7
END
select #End_Date =
CAST(DATEADD(DAY,
CASE WHEN (#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7)) = 7
THEN 0
WHEN (#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7)) < 0
THEN 7 - ABS(#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7))
ELSE (#DoW - (((##datefirst) + datepart(weekday, #DateInWeek)) % 7) )
END
,#DateInWeek) AS DATE)
RETURN #End_Date
END
This will give you the Friday of Last week.
SELECT DATEADD(day, -3 - (DATEPART(dw, GETDATE()) + ##DATEFIRST - 2) % 7, GETDATE()) AS LastWeekFriday
This will give you last Friday's Date.
SELECT DATEADD(day, +4 - (DATEPART(dw, GETDATE()) + ##DATEFIRST-2) % 7, GETDATE()) AS LastFriday
select convert(varchar(10),dateadd(d, -((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate()),101)
Following code can be use to return any last day by replacing #dw_wk, test case below use friday as asked in original questions
DECLARE #date SMALLDATETIME
,#dw_wk INT --last day of week required - its integer representation
,#dw_day int --current day integer reprsentation
SELECT #date='8/11/2012'
SELECT #dw_day=DATEPART(dw,#date)
SELECT #dw_wk=DATEPART(dw,'1/2/2015') --Just trying not to hard code 5 for friday, here we can substitute with any date which is friday
SELECT case when #dw_day<#dw_wk then DATEADD(DAY, #dw_wk-7-#dw_day,#date) else DATEADD(DAY,#dw_wk-#dw_day, #date) END
Here's an answer I found here adapted from MySQL to T-SQL that is a one liner using all basic arithmetic (no division or modulos):
SELECT DATEADD(d, 1 - datepart(weekday, dateadd(d, 2, GETDATE())), GETDATE())
You can do all sorts of combinations of this, like get next Friday's date unless today is Friday, or get last Thursday's date unless today is Thursday by just changing the 1 and the 2 literals in the command:
Get next Friday's date unless today is Friday
SELECT DATEADD(d, 7 - datepart(weekday, dateadd(d, 1, GETDATE())), GETDATE())
Get last Thursday's date unless today is Thursday
SELECT DATEADD(d, 1 - datepart(weekday, dateadd(d, 3, GETDATE())), GETDATE())
I have had this same issue, and created the following example to show how to do this and to make it flexible to use whichever day of the week you want. I have different lines in the SELECT statement, just to show what this is doing, but you just need the [Results] line to get the answer. I also used variables for the current date and the target day of the week, to make it easier to see what needs to change.
Finally, there is an example of results when you want to include the current date as a possible example or when you always want to go back to the previous week.
DECLARE #GetDate AS DATETIME = GETDATE();
DECLARE #Target INT = 6 -- 6 = Friday
SELECT
#GetDate AS [Current Date] ,
DATEPART(dw, #GetDate) AS [Current Day of Week],
#Target AS [Target Day of Week] ,
IIF(#Target = DATEPART(dw, #GetDate), 'Yes' , 'No') AS [IsMatch] ,
IIF(#Target = DATEPART(dw, #GetDate), 0 , ((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7) AS [DateAdjust] ,
------------------------------------------------------------------------------------------------------------------------------------------------
CAST(IIF(#Target = DATEPART(dw, #GetDate), #GetDate, DATEADD(d, (((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7), #GetDate)) AS DATE) AS [Result]
------------------------------------------------------------------------------------------------------------------------------------------------
;
SELECT
#GetDate AS [Current Date] ,
DATEPART(dw, #GetDate) AS [Current Day of Week],
#Target AS [Target Day of Week] ,
((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7 AS [DateAdjust] ,
------------------------------------------------------------------------------------------------------------------------------------------------
CAST(DATEADD(d, (((7 + #Target - DATEPART(dw, #GetDate)) % 7) - 7), #GetDate) AS DATE) AS [NOTIncludeCurrent]
------------------------------------------------------------------------------------------------------------------------------------------------
;
SELECT DECODE(TO_CHAR(SYSDATE,'DY'),'FRI',SYSDATE,NEXT_DAY(SYSDATE, 'FRI')-7) FROM dual;

Get the most recent Friday's date SQL

I'm trying to get the most recent Friday in SQL Server 2008.
I have this. It gets the beginning of the week (monday) then subtracts 3 days to get Friday.
declare #recentFriday datetime = DATEADD(ww, DATEDIFF(dd,0,GETDATE()), 0)-3
When this is run during the week, it gets last Friday's date which is correct. But when run on Friday (or Saturday), it still gets last week's date instead of the current week's Friday. I'm about to use if/else conditions but I'm sure there's an easier way.
This works for any input and any setting of DATEFIRST:
dateadd(d, -((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
It works by adjusting the weekday value so that 0 = Friday, simulating Friday as the beginning of the week. Then subtract the weekday value if non-zero to get the most recent Friday.
Edit: Updated to work for any setting of DATEFIRST.
DECLARE #date DATETIME = '20110512' -- Thursday
SELECT DATEADD(DAY,-(DATEDIFF(DAY,'19000105',#date)%7),#date) --20110506
SET #date = '20110513' -- Friday
SELECT DATEADD(DAY,-(DATEDIFF(DAY,'19000105',#date)%7),#date) --20110513
SET #date = '20110514' -- Saturday
SELECT DATEADD(DAY,-(DATEDIFF(DAY,'19000105',#date)%7),#date) --20110513
Calculate the number of days between a known Friday (05 Jan 1900) and the given date
The remainder left from dividing the difference in 1. by 7 will be the days elapsed since the last Friday
Subtract the remainder in 2. from the given date
you can check if the current day of week is friday or greater DATEPART(dw,GETDATE()) and then call (SELECT DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)+4) or (SELECT DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)-3)
SELECT
CASE WHEN DATEPART(dw,GETDATE()) >= 5 THEN
(SELECT DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)+4)
ELSE
(SELECT DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)-3)
END
Using a known Friday date (I'll use Jan 7, 2011) as a starting point, you can do this:
DECLARE #d DATETIME
SET #d = '2011-05-13' /* Friday */
SELECT DATEADD(DAY, (DATEDIFF (DAY, '20110107', #d) / 7) * 7, '20110107')
/* Returns 2011-05-13 */
SET #d = '2011-05-12' /* Thursday */
SELECT DATEADD(DAY, (DATEDIFF (DAY, '20110107', #d) / 7) * 7, '20110107')
/* Returns 2011-05-06 */
Just choose a known Friday that's older than any dates you'll be using in your calculations.
SELECT CONVERT(VARCHAR(12),GETDATE()) AS Today,
CASE WHEN (DATEPART(DW,GETDATE())< 7)
THEN CONVERT(VARCHAR(12),(DATEADD(dd,-(DATEPART(DW,GETDATE())+1),GETDATE())))
ELSE CONVERT(VARCHAR(12),(DATEADD(d,- 1,GETDATE())))
END AS [Last Friday]
Here is a completly set oriented way to achive the last Friday:
select Friday from
(
select max(GetDate()) as Friday where datepart(dw, getdate()) = 6
union all
select max((GetDate() - 1)) where datepart(dw, (getdate() - 1)) = 6
union all
select max((GetDate() - 2)) where datepart(dw, (getdate() - 2)) = 6
union all
select max((GetDate() - 3)) where datepart(dw, (getdate() - 3)) = 6
union all
select max((GetDate() - 4)) where datepart(dw, (getdate() - 4)) = 6
union all
select max((GetDate() - 5)) where datepart(dw, (getdate() - 5)) = 6
) x where Friday is not null
The other solutions were not working for my use case.
This works for finding any previous day by replacing 'Sunday' with the day you`re looking for:
DECLARE #myDate DATE = GETDATE()
WHILE DATENAME(WEEKDAY, #myDate) <> 'Sunday'
BEGIN
SET #myDate = DATEADD(DAY, -1, #myDate)
END
This is what I got I hope it helps
DECLARE #UserDate DateTime
SET #UserDate = '2020-09-03'
SELECT DATEADD(day, (6 - datepart(weekday, #UserDate)) , #UserDate)

Finding Day in T-SQL

Please let me know how can I find if it is Sunday on given Date?
EDIT:
From answers another thing comes to my mind: How to find what is first day of week?
Use the "datename" function:
print datename(weekday, '11/29/2009')
or with a variable:
declare #date smalldatetime
set #date = '12/25/2008'
select datename(weekday, #date)
SELECT DATEPART(dw,theDateRow) AS dateOfWeek FROM someTable
dw stands for Day of Week
if dw = 0, it is Sunday.
A) Sunday Check
SELECT
CASE WHEN DATENAME(WEEKDAY, GETDATE()) != 'Sunday'
Then 'It is ' + CAST(DATENAME(WEEKDAY, GETDATE()) AS VARCHAR(10))
Else 'It is ' + CAST(DATENAME(WEEKDAY, GETDATE()) AS VARCHAR(10))
END 'Day is'
Output:
Day is
It is Saturday
B) Find first day of week
SELECT
DayName = DATENAME(WEEKDAY,
DATEADD(DD, 1 - DATEPART(DW, CONVERT(VARCHAR(10), GETDATE(), 111)),
CONVERT(VARCHAR(10), GETDATE(), 111))),
Date = DATEADD(DD,
1 - DATEPART(DW, CONVERT(VARCHAR(10), GETDATE(), 111)),
CONVERT(VARCHAR(10), GETDATE(), 111))
Output:
DayName Date
Sunday 2009-12-27 00:00:00.000
To find what is the first day of the week you use:
print ##datefirst
This will return a number from 1 to 7, where 1 = Monday, 2 = Tuesday... 7 = Sunday. You can change what is considered the first day of the week (on the SQL instance) by using:
set datefirst = 1
This will set the first day to Monday. By default SQL is set to 7 (Sunday) in US.