SQL Query Help: Transforming Dates In A Non-Trivial Way - sql

I have a table with a "Date" column, and I would like to do a query that does the following:
If the date is a Monday, Tuesday, Wednesday, or Thursday, the displayed date should be shifted up by 1 day, as in DATEADD(day, 1, [Date]) On the other hand, if it is a Friday, the displayed date should be incremented by 3 days (i.e. so it becomes the following Monday).
How do I do this in my SELECT statement? As in,
SELECT somewayofdoingthis([Date]) FROM myTable
(This is SQL Server 2000.)

Here is how I would do it. I do recommend a function like above if you will be using this in other places.
CASE
WHEN
DATEPART(dw, [Date]) IN (2,3,4,5)
THEN
DATEADD(d, 1, [Date])
WHEN
DATEPART(dw, [Date]) = 6
THEN
DATEADD(d, 3, [Date])
ELSE
[Date]
END AS [ConvertedDate]

CREATE FUNCTION dbo.GetNextWDay(#Day datetime)
RETURNS DATETIME
AS
BEGIN
DECLARE #ReturnDate DateTime
set #ReturnDate = dateadd(dd, 1, #Day)
if (select datename(#ReturnDate))) = 'Saturday'
set #ReturnDate = dateadd(dd, 2, #ReturnDate)
if (select datename(#ReturnDate) = 'Sunday'
set #ReturnDate = dateadd(dd, 1, #ReturnDate)
RETURN #ReturnDate
END

Try
select case when datepart(dw,[Date]) between 2 and 5 then DATEADD(dd, 1, [Date])
when datepart(dw,[Date]) = 6 then DATEADD(dd, 3, [Date]) else [Date] end as [Date]

I'm assuming that you also want Saturday and Sunday to shift forward to the following Monday. If that is not the case, take the 1 out of (1,2,3,4,5) and remove the last when clause.
case
--Sunday thru Thursday are shifted forward 1 day
when datepart(weekday, [Date]) in (1,2,3,4,5) then dateadd(day, 1, [Date])
--Friday is shifted forward to Monday
when datepart(weekday, [Date]) = 6 then dateadd(day, 3, [Date])
--Saturday is shifted forward to Monday
when datepart(weekday, [Date]) = 7 then dateadd(day, 2, [Date])
end
You can also do it in one line:
select dateadd(day, 1 + (datepart(weekday, [Date])/6) * (8-datepart(weekday, [Date])), [Date])

Sounds like a CASE expression. I don't know the proper data manipulations for SQL Server, but basically it would look like this:
CASE
WHEN [Date] is a Friday THEN DATEADD( day, 3, [Date] )
ELSE DATEADD( day, 1, [Date] )
END
If you wanted to check for weekend days you could add additional WHEN clauses before the ELSE.

you could use this:
select dayname,newdayname =
CASE dayname
WHEN 'Monday' THEN 'Tuesday'
WHEN 'Tuesday' THEN 'Wednesday'
WHEN 'Wednesday' THEN 'Thursday'
WHEN 'Thursday' THEN 'Friday'
WHEN 'Friday' THEN 'Monday'
WHEN 'Saturday' THEN 'Monday'
WHEN 'Sunday' THEN 'Monday'
END
FROM UDO_DAYS
results:
Monday Tuesday
Tuesday Wednesday
Wednesday Thursday
Thursday Friday
Friday Monday
Saturday Monday
Sunday Monday
table data:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday

Look up the CASE statement and the DATEPART statement. You will want to use the dw argument with DATEPART to get back an integer that represents the day of week.

This is off the top of my head and can be clearly cleaned up but use it as a starting point:
select case when DATENAME(dw, [date]) = 'Monday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Tuesday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Wednesday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Thursday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Friday' then DATEADD(dw, 3, [Date])
end as nextDay
...

How about taking a page from the Data Warehouse guys and make a table. In DW terms, this would be a date dimension. A standard date dimension would have things like various names for a date ("MON", "Monday", "August 22, 1998"), or indicators like end-of-month and start-of-month. However, you can also have columns that only make sense in your environment.
For instance, based on the question, yours might have a next-work-day column that would point to the key for the day in question. That way you can customize it further to take into account holidays or other non-working days.
The DW folks are adamant about using meaningless keys (that is, don't just use a truncated date as the key, use a generated key), but you can decide that for yourself.
The Date Dimension Toolkit has code to generate your own tables in various DBMS and it has CSV data for several years worth of dates.

you need to create a SQL Function that does this transformation for you.

This is mostly like Brian's except it didn't compile due to mismatched parens and I changed the IF to not have the select in it. It is important to note that we use DateNAME here rather than datePART because datePART is dependent on the value set by SET DATEFIRST, which sets the first day of the week.
CREATE FUNCTION dbo.GetNextWDay(#Day datetime)
RETURNS DATETIME
AS
BEGIN
DECLARE #ReturnDate DateTime
set #ReturnDate = dateadd(dd, 1, #Day)
if datename(dw, #ReturnDate) = 'Saturday'
set #ReturnDate = dateadd(dd, 2, #ReturnDate)
if datename(dw, #ReturnDate) = 'Sunday'
set #ReturnDate = dateadd(dd, 1, #ReturnDate)
RETURN #ReturnDate
END

create table #dates (dt datetime)
insert into #dates (dt) values ('1/1/2001')
insert into #dates (dt) values ('1/2/2001')
insert into #dates (dt) values ('1/3/2001')
insert into #dates (dt) values ('1/4/2001')
insert into #dates (dt) values ('1/5/2001')
select
dt, day(dt), dateadd(dd,1,dt)
from
#dates
where
day(dt) between 1 and 4
union all
select
dt, day(dt), dateadd(dd,3,dt)
from
#dates
where
day(dt) = 5
drop table #dates

Related

Get the date of Sunday and Saturday 2 weeks ago

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 ;

Getting SQL to return data ONLY for the last business day

I have tried about a thousand different ways to attempt this after hours of scouring the internet and finding things that seem like they would work, I still have not been able to get this to come up correctly.
I have a query that I am running in SQL via Tableau that I need to be dynamic and change to look at ONLY business days. When I updated my query this morning, since our server looks at one day prior, it was looking for Sunday data which in my company there is no processing going on on Saturday or Sunday, I need it to know when today is Monday, (basically) do getdate()-3, otherwise, getdate()-1.
I have tried declaring a variable, I have tried something like this:
SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
which doesn't work because the column from my table called create_date to be set to the correct dynamic date. This works if I run it alone without trying to incorporate into a query (gives me the date for Friday) but I can not figure out how to then take that date and apply it to my query.
This is the closest I have been able to get
DECLARE #CREATIONDAY DATE
SET #CREATIONDAY = DAY, CASE DATENAME(WEEKDAY, convert(date,GETDATE()))
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()));
SELECT CREATION_DATE, COUNT(*)
FROM [dbo].[workflow_document]
WHERE CREATION_DATE = #CREATIONDAY
GROUP BY CREATION_DATE
but still getting an error "Msg 102, Level 15, State 1, Line 3
Incorrect syntax near ','."
Not sure what could be wrong with the comma, but I am about at the end of my rope with getting this to work. Anything is appreciated!
Your method is fine. Your variable definition has DAY, in it. So:
SET #CREATIONDAY = DATEADD(DAY,
(CASE DATENAME(WEEKDAY, convert(date,GETDATE()))
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1
END),
GETDATE());
Or, just add the logic into the WHERE clause:
WHERE (DATENAME(WEEKDAY, GETDATE()) = 'Sunday' AND
CREATION_DATE = DATEADD(DAY, -2, CAST(GETDATE as DATE))
) OR
(DATENAME(WEEKDAY, GETDATE()) = 'Monday' AND
CREATION_DATE = DATEADD(DAY, -3, CAST(GETDATE as DATE))
) OR
(DATENAME(WEEKDAY, GETDATE()) = 'Sunday' AND
CREATION_DATE = DATEADD(DAY, -2, CAST(GETDATE as DATE))
) OR
(DATENAME(WEEKDAY, GETDATE()) NOT IN ('Sunday', 'Monday') AND
CREATION_DATE = DATEADD(DAY, -1, CAST(GETDATE as DATE))
)
When dealing with day-of-week calculations, it's important to take account of the current DATEFIRST settings. This query will always correctly exclude weekend days, using ##DATEFIRST to account for any possible setting for the first day of the week.
SELECT *
FROM your_table
WHERE ((DATEPART(dw, date_created) + ##DATEFIRST) % 7) NOT IN (0, 1)

DATEDIFF between two dates, excluding two specific days

In Dubai, the standard weekend runs from Friday - Saturday rather than the traditional Saturday / Sunday.
I am trying to calculate the amount of working days between two given dates, and this is the code I have;
DATEDIFF(dd, DATEADD(hour, DATEDIFF(hh, getdate(), getutcdate()), #StartDate),
DATEADD(hour, DATEDIFF(hh, getdate(), getutcdate()), #EndDate)+1)
-
(
(DATEDIFF(wk, #StartDate, #EndDate) * 2
+(CASE WHEN DATENAME(dw, #StartDate) = 'Saturday' then 1 else 0 end)
+(CASE WHEN DATENAME(dw, #EndDate) = 'Friday' then 1 else 0 end)
))
)
However it is calculating the wrong amount of days. For example;
When the start date is 02-03-2016 and the end date is 02-06-2016 the returns as 4, but it should be 2.
When the start date is 02-03-2016 and the end date is 02-07-2016 the result is 3 which is correct.
The code below calculates the working days from your examples correctly. You can wrap it in a scalar function if you want.
declare #from date, #to date;
set #from = '2016-02-03';
set #to = '2016-02-06';
with dates(date)
as
(
select #from
union all
select dateadd(dd, 1, [date])
from dates
where [date] < #to
)
select count(*) [working days]
from (
select date, case when datename(dw, [date]) in ('Friday', 'Saturday') then 0 else 1 end as working
from dates) as dt
where dt.working = 1

count week days in sql by datediff [duplicate]

This question already has answers here:
Count work days between two dates
(24 answers)
Calculating days to excluding weekends (Monday to Friday) in SQL Server
(6 answers)
Closed 7 years ago.
I'm looking for a way to calculate the days between two dates, but on weekdays. Here is the formula, but it counts weekend days.
DATEDIFF(DAY,STARTDATE,ENDDATE)
SELECT DATEDIFF(DAY,'2015/06/01' , '2015/06/30')
Result of above query of datediff is 29 days which are weekend days. but i need week days that should be 21 by removing Saturday and Sunday(8 days).
Any suggestions?
Put it in the WHERE clause
SELECT DATEDIFF(DAY,'2015/06/01' , '2015/06/30')
FROM yourtable
WHERE DATENAME(dw, StartDate) != 'Saturday'
AND DATENAME(dw, StartDate) != 'Sunday'
Or all in a SELECT statement
SELECT (DATEDIFF(dd, StartDate, EndDate) + 1)-(DATEDIFF(wk, StartDate, EndDate) * 2)-(CASE WHEN DATENAME(dw, StartDate) = 'Sunday' THEN 1 ELSE 0 END)-(CASE WHEN DATENAME(dw, EndDate) = 'Saturday' THEN 1 ELSE 0 END)
This returns 22:
DECLARE #StartDate AS DATE = '20150601'
DECLARE #EndDate AS DATE = '20150630'
SELECT
(DATEDIFF(DAY, #StartDate, #EndDate))
-(DATEDIFF(WEEK, #StartDate, #EndDate) * 2)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #EndDate) = 'Saturday' THEN 1 ELSE 0 END)
Read this article by Jeff Moden for more information.
Explanation:
First, (DATEDIFF(DAY, #StartDate, #EndDate)) will return the difference in number of days. In this case, it'll be 29. Now, depending on your interpretation of whole days, you may want to add 1 day to its result.
Next,(DATEDIFF(WEEK, #StartDate, #EndDate) * 2):
To quote the article:
DATEDIFF for the WEEK datepart doesn't actually calculate weeks, it
calculates the number of times a date range contains dates that
represent pairs of Saturdays and Sundays. To think of it in more
simple terms, it only counts WHOLE WEEKENDS!
So, to exclude the weekends, you must subtract twice the result of this from the first DATEDIFF. Which now will be: 29 - (2 *4) = 21.
Finally, this:
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #EndDate) = 'Saturday' THEN 1 ELSE 0 END)
removes the partial weeks, which only happens when then #StartDate occurs on a Sunday and the #EndDate occurs on a Saturday.
You can try recursive cte:
WITH cte
AS ( SELECT CAST('2015/06/01' AS DATE) AS dt ,
DATEPART(WEEKDAY, '2015/06/01') AS wd
UNION ALL
SELECT DATEADD(d, 1, dt) AS dt ,
DATEPART(WEEKDAY, DATEADD(d, 1, dt))
FROM cte
WHERE dt < '2015/06/30'
)
SELECT COUNT(*)
FROM cte
WHERE wd NOT IN ( 7, 1 )
Result is 22.
You better add some useful calendar table that every database should have. Fill it with some big range and then use it to calculate business days.
I wrote a simple stored procedure - don't know if a SP is what you need but i think you can easily convert it to a function , TVF, whatever:
CREATE PROCEDURE [dbo].[BusinessdaysBetween](#DateFrom DATE, #DateTo DATE, #days INT OUTPUT)
AS
BEGIN
DECLARE #datefirst INT = ##DATEFIRST
SET DATEFIRST 1 --so week starts on monday
SET #days = 0
IF #DateFrom > #DateTo
RETURN NULL
IF #DateFrom = #DateTo
RETURN #days
WHILE #DateFrom <= #DateTo
BEGIN
IF DATEPART(WEEKDAY,#DateFrom) NOT IN (6,7) --Saturday or Sunday
BEGIN
SET #days = #days + 1
END
SET #DateFrom = DATEADD(DAY,1,#DateFrom)
END
SET DATEFIRST #datefirst --restore original setup
END
GO
in my example i call i it like this:
DECLARE #days INT = 0
DECLARE #datefrom DATETIME = GETDATE()
DECLARE #dateto DATETIME = DATEADD(DAY,25,GETDATE())
EXEC dbo.BusinessdaysBetween #datefrom, #dateto, #days OUTPUT
SELECT #days

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;