How to find last weekday of current month using SQL - sql

How would I calculate the last weekday of the current month given a date using SQL?
I was able to get the last day of current month, but not sure how to do the last weekday programmatically.
I don't want to generate a calendar look-up table.
Here's the last day of month code i'm currently using:
declare #date datetime
set #date='1/4/13'
select DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))

Quite a neat solution:
declare #date1 as date = '20130401'
declare #date as date= eomonth(#date1,0)
set #date = (select case
when datepart(dw,#date) = 1 then dateadd(day,-2,#date) --when day is a sunday subtract 2 day to friday
when datepart(dw,#date) = 7 then dateadd(day,-1,#date) --when day is a saturday subtract 1 day to friday
else #date END)

I know that this is old, but I was looking for a one-liner and landed here. Here's the one I figured out:
set DATEFIRST 1
declare #testDate datetime
select #testDate = '8/1/2016'
select dateadd(day, -(select max(dayCount) from (values (DATEPART(WEEKDAY, EOMONTH(#testDate)) - 5), (0 )) as allDays(dayCount)), EOMONTH(#testDate))
This will only work with SQL Server 2012 and above.
How it works:
Get the last calendar date for the test date
Get the day-of-the week where Monday is 1, Saturday is 6 and Sunday
is 7
Subtract the day-of-the week and then set it to 0 if it is negative,
practically a max(0, day-of-the week - 5). This will leave 1 for Saturday or 2 for Sunday.
Subtract the days (1 if Saturday, 2 if Sunday) from the last day of
the month

I know it is not the most intuitive or effective or easy way of doing it. But here is my solution to find the last Weekday of the month...
declare #date datetime, #lastDate datetime, #lastWeekDay datetime
set #date='05/4/2014';--'1/1/2014'
set #lastDate = (SELECT DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0)));
/* #dayOfWeek represents -- 0-Monday through 7-Sunday */
declare #dayOfWeek INT = (SELECT DATEDIFF(dd, 0, #lastDate) % 7);
/* If last date is sat/sun substract 1 or 2 days from last date */
set #lastWeekDay = (SELECT CASE WHEN #dayOfWeek = 5 THEN DATEADD(dd, -1, #lastDate)
WHEN #dayOfWeek = 6 THEN DATEADD(dd, -2, #lastDate)
ELSE #lastDate END)
SELECT #lastWeekDay;

This one is much harder than it ought to be. I’ve done similar work using datename, but only because I know all the systems I use will be configured with English as the default language. Without that assumption, you have to use datepart(dw, ..., and you also have to worry about SET DATEFIRST. I am also assuming “weekday” means “Mon, Tue, Wed, Thu, Fri”, and excluding Saturday and Sunday. (Or does TFIG apply across the globe?)
Thus, walking through my methodology, we start with what you had:
DECLARE
#Date datetime
,#BOM datetime
--SET #Date = '1/4/14' -- Should return Jan 31, 2013
SET #Date = '5/4/14' -- Should return May 30, 2014 (not May 31)
SET #BOM = DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0)
PRINT #BOM
This sets #BOM (beginning of month) to the first day of the month after whatever you have in #Date. (I split this across multiple statements, because otherwise you have to repeat the function all over the place in the code below.)
Next, you have to “move back” from this day by one, two, or three days. If BOM is Monday, -3 to get to the prior Friday; if BOM is Sunday, -2 to get to Friday; otherwise, -1 will land you on a weekday. Based on the values returned by datepart, there’s no wifty algorithm I can think of to generate that -1/-2/-3 spread, so I use a case statement (I reject looping routines out of hand—far too kludgy for database work).
PRINT datepart(dw, #BOM) -- To see what is is
PRINT dateadd(dd, case
when datepart(dw, #BOM) = 2 then -3
when datepart(dw, #BOM) = 1 then -2
else -1
end
,#BOM)
Alas, this only works if your SQL instance is configured with the default “first day of week” setting; this is checked via PRINT ##datefirst, where 7 (the default) = Sun, 6 = Sat, and so forth. Once again, no wifty algorithm suggests itself, and the case statement turns into a mess:
PRINT dateadd(dd, case
when ##datefirst = 7 and datepart(dw, #BOM) = 2 then -3
when ##datefirst = 7 and datepart(dw, #BOM) = 1 then -2
when ##datefirst = 6 and datepart(dw, #BOM) = 3 then -3
when ##datefirst = 6 and datepart(dw, #BOM) = 2 then -2
when ##datefirst = 5 and datepart(dw, #BOM) = 4 then -3
when ##datefirst = 5 and datepart(dw, #BOM) = 3 then -2
when ##datefirst = 4 and datepart(dw, #BOM) = 5 then -3
when ##datefirst = 4 and datepart(dw, #BOM) = 4 then -2
when ##datefirst = 3 and datepart(dw, #BOM) = 6 then -3
when ##datefirst = 3 and datepart(dw, #BOM) = 5 then -2
when ##datefirst = 2 and datepart(dw, #BOM) = 7 then -3
when ##datefirst = 2 and datepart(dw, #BOM) = 6 then -2
when ##datefirst = 1 and datepart(dw, #BOM) = 1 then -3
when ##datefirst = 1 and datepart(dw, #BOM) = 7 then -2
else -1
end
,#BOM)
Ugly, or what? And looping structures have to account for this as well. Of course, if you can rely on always having the same language on your SQL Instances, it’s that much simpler:
PRINT dateadd(dd, case
when datename(dw, #BOM) = 'Monday' then -3
when datename(dw, #BOM) = 'Sunday' then -2
else -1
end
,#BOM)
Any or all of the above can and should be “concatenated down” into a single statement or query (or, better, a function); if you can safely make assumptions about your installation’s language and/or first day of week, you can shorten it even more.

you can try using the week day function like
select datename(dw, getdate())
and then from there use that in your query to derive the last week day in the month
so you could end up with something like this without actually having to create a "dates" table
declare #date datetime
set #date='3/4/13'
select case when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))) = 'Saturday'
then DATEADD(d, -2, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))
when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))) = 'Sunday'
then DATEADD(d, -3, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))
else DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))
end
, case when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))) = 'Saturday'
then datename(dw, DATEADD(d, -2, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0)))
when datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0))) = 'Sunday'
then datename(dw, DATEADD(d, -3, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0)))
else datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0)))
end

declare #date datetime ='1/4/19'
select datename(dw, DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #date) + 1, 0)))
This will give you the day name of the last day of the month.

select case when datename(dw,(EOMONTH(getdate()))) ='Saturday' then day(EOMONTH(getdate())) -1
when datename(dw,(EOMONTH(getdate()))) ='Sunday' then day(EOMONTH(getdate())) -2
else day(EOMONTH(getdate())) end

Related

Subtracting one month from a date but making sure it is the first business day of that month

I need to subtract one month from a date called ArchiveDate but I want the first business day of that month. For example if my ArchiveDate is 9/2/2018 I would like to have 8/1/2019.
This is what I have:
DECLARE #ArchiveDate date = '9/2/2019'
SELECT ArchiveDate = DATEADD(day,
CASE WHEN
DATEPART(weekday, DATEADD(MONTH, -1, #ArchiveDate)) = 1
THEN 1
WHEN DATEPART(weekday, DATEADD(MONTH, -1, #ArchiveDate)) = 7 THEN 2
ELSE 0
END
, DATEADD(MONTH, -1, #ArchiveDate))
What I get from this is 8/2/2019 but as you can see I want 8/1/2019.
SELECT
CASE
WHEN DATENAME(WEEKDAY, DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0)) = 'Saturday'
THEN DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0) + 2
WHEN DATENAME(WEEKDAY, DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0)) = 'Sunday'
THEN DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0) + 1
ELSE
DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0)
END
This will return the first BUSINESS DAY of the previous month.
you can use eomonth along with your logic to get first day of previous month as below:
DECLARE #ArchiveDate date = '9/2/2019'
select dateadd(day, 1, eomonth(dateadd(month, -2, #ArchiveDate)));
You can use EOMONTH with DATEADD():
SELECT DATEADD(DAY, 1, EOMONTH(#ArchiveDate, -2)) AS ArchiveDate

How to return just the yyyy-mm-dd from the following SQL queries [duplicate]

This question already has answers here:
How to get a date in YYYY-MM-DD format from a TSQL datetime field?
(25 answers)
Closed 4 years ago.
Below are the queries I created. Query #1 returns 2018-07-06 00:00:00.000 and query #2 returns 2018-07-31 23:59:59.997.
I can't figure out how to modify the queries so that they'll return the result in the yyyy-mm-dd format. Please advice.
Query #1 - get fifth business day of the month
SELECT
FifthWeekDay = DATEADD(dd, CASE
WHEN DATEDIFF(dd, -1, ca.FirstOfMonth) % 7 > 1 -- -1 is a Sunday
THEN 7
ELSE 6 - DATEDIFF(dd, -1, ca.FirstOfMonth) % 7 -- -1 is a Sunday
END, ca.FirstOfMonth - 1)
FROM
(SELECT
DATEADD(mm, (SELECT DATEPART(YEAR, GETDATE())) * 12 - 22801 +
(SELECT DATEPART(M, GETDATE())), 0)) ca(FirstOfMonth)
Query #2 - get last business day of the month
SELECT
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0))
- CASE DATENAME(dw, DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0)))
WHEN 'SUNDAY' THEN 2
WHEN 'SATURDAY' THEN 1
ELSE 0
END AS LastBusinessCurrentMonth
You can subquery the results you already have and add a cast( as date):
SELECT CAST(LastBusinessCurrentMonth AS DATE) AS LastBusinessCurrentMonth FROM(
SELECT
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0))
- CASE DATENAME(dw, DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0)))
WHEN 'SUNDAY' THEN 2
WHEN 'SATURDAY' THEN 1
ELSE 0
END AS LastBusinessCurrentMonth) AS X
SELECT CAST(FIFTHWEEKDAY AS DATE) AS FIFTHWEEKDAY FROM(
SELECT
FifthWeekDay = DATEADD(dd, CASE
WHEN DATEDIFF(dd, -1, ca.FirstOfMonth) % 7 > 1 -- -1 is a Sunday
THEN 7
ELSE 6 - DATEDIFF(dd, -1, ca.FirstOfMonth) % 7 -- -1 is a Sunday
END, ca.FirstOfMonth - 1)
FROM
(SELECT
DATEADD(mm, (SELECT DATEPART(YEAR, GETDATE())) * 12 - 22801 +
(SELECT DATEPART(M, GETDATE())), 0)) ca(FirstOfMonth)) AS X
Or you could declare a variable as Date and set the results of your queries to that variable :
DECLARE #DATEVAR DATE
SET #DATEVAR =(
SELECT
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0))
- CASE DATENAME(dw, DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0)))
WHEN 'SUNDAY' THEN 2
WHEN 'SATURDAY' THEN 1
ELSE 0
END AS LastBusinessCurrentMonth)
SELECT #DATEVAR AS LastBusinessCurrentMonth
SET #DATEVAR = (SELECT
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0))
- CASE DATENAME(dw, DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0)))
WHEN 'SUNDAY' THEN 2
WHEN 'SATURDAY' THEN 1
ELSE 0
END AS LastBusinessCurrentMonth)
SELECT #DATEVAR AS LastBusinessCurrentMonth

SQL - pick current date from machine and compare

For the below query
Scenario 1: Current Year (Previous Week) - For eg- Week 31
sum(case when s.Date between '2016-07-17' and '2016-07-23' then s.SELLINC else 0 end) ActualSales
Scenario 2: Last Year (Previous Week) - For eg- Week 31
sum(case when s.Date between '2015-07-19' and '2015-07-25' then s.SELLINC else 0 end) LastYrVarianc
Scenario 3: Picking dates between beginning of current year till today's date
sum(case when s.Date between '2016-01-01' and '2016-09-05' then s.SELLINC else 0 end) YrToDateActual
Scenario 4: Picking dates between beginning of last year till last year today's date
sum(case when s.Date between '2015-01-01' AND '2015-09-05' then s.SELLINC else 0 end) LastYrToDateActual
Instead of hard coding the date. I would like to pick current date from machine and compare.
Week start from Sunday and ends Saturday. Any help please?
First off, GETDATE() is the SQL Server function for today's date
DATEADD(..) is the function to add stuff to dates
1) case when s.date between DATEADD(dd,-6,getdate()) and getdate()) then...
2) case when s.date between DATEADD(yy,-1,DATEADD(dd,-6,getdate())) and DATEADD(yy,-1,getdate()) then ...
3) case when s.date between DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) and getdate() then ...
4) case when s.date between dateadd(yy,-1,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) and DATEADD(yy,-1,GETDATE()) then ..
A little help from here
I assume that your week starts from sunday to saturday.
You can use this query,
Scenario-1 (PreviousWeekStartDate and PreviousWeekEndDate)
s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
Scenario-2 (LastYearPreviousWeekStartDate and LastYearPreviousWeekEndDate)
s.Date between convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5)
Scenario-3 (StartOfYear and CurrentDate)
s.Date between convert(date,DATEADD(yy, DATEDIFF(yy, 0, getdate()), 0)) and convert(date,getdate())
Scenario-4 (StartOfLastYear and CurrentDateLastYear)
s.Date between convert(date,DATEADD(yy, DATEDIFF(yy, 0, dateadd(YEAR, - 1, getdate())), 0)) and convert(date,dateadd(YEAR, - 1, getdate()))
Use date arithmetic
declare #weekNo int = 31;
--start of the year
declare #ys datetime = dateadd(year,datediff(year,0,getdate()),0)
-- start of the first week of the year (may start in December of prev year)
declare #y1ws datetime = dateadd(week,datediff(week,0,#ys),0)
select #ys, #y1ws, dateadd(week, #weekNo-1, #y1ws) [week31 start], dateadd(week, #weekNo, #y1ws) [week32 start]
-- use it this way for week 31
-- .. where somedate >= [week31 start] and somedate < [week32 start]
SELECT
GETDATE(), -- Today
DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0), -- Start of this year
DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) - 1, 0), -- Start of last year
DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()), 0), -- Start of this week
DATEADD(WEEK, DATEDIFF(WEEK, 0, GETDATE()) - 1, 0) -- Start of last week
I think using DATEPART (Transact-SQL) is a more portable solution. My answers for scenario 1 and scenario 2 refer a natural week starting from Sunday, which are different from JohnHC's answers (referring last 7 days).
--
-- Scenario 1: Current Year (Previous Week) - For eg- Week 31
--
CASE WHEN
DATEPART(ww, s.Date) = DATEPART(ww, GETDATE()) - 1 AND
DATEPART(yy, s.Date) = DATEPART(yy, GETDATE())
THEN ...
--
-- Scenario 2: Last Year (Previous Week) - For eg- Week 31
--
CASE WHEN
DATEPART(ww, s.Date) = DATEPART(ww, GETDATE()) - 1 AND
DATEPART(yy, s.Date) = DATEPART(yy, GETDATE()) - 1
THEN ...
--
-- Scenario 3: Picking dates between beginning of current year till today's date
--
CASE WHEN
DATEPART(yy, s.Date) = DATEPART(yy, GETDATE())
THEN ...
--
-- Scenario 4: Picking dates between beginning of last year till last year today's date
--
CASE WHEN
DATEPART(yy, s.Date) >= DATEPART(yy, GETDATE()) - 1
THEN ...

First business day of the current month - SQL Server

How could I get the first business day of the current month?
Without create a function, only select.
something like that:
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(GETDATE())-1), GETDATE()), 101)
somebody knows please?
Thanks.
A Simple case statement could do it
SELECT CASE
WHEN DATENAME(WEEKDAY, dateadd(mm, DATEDIFF(MM, 0, getdate()), 0)) = 'Saturday'
THEN dateadd(mm, DATEDIFF(MM, 0, getdate()), 0) + 2
WHEN DATENAME(WEEKDAY, dateadd(mm, DATEDIFF(MM, 0, getdate()), 0)) = 'Sunday'
THEN dateadd(mm, DATEDIFF(MM, 0, getdate()), 0) + 1
ELSE dateadd(mm, DATEDIFF(MM, 0, getdate()), 0)
END
This will literally give you what you're asking for -- the first business day in a month if we define a business day as "any day that's not a Saturday or a Sunday". But this is is a very narrow definition of "business day" that is not appropriate when taking into account holidays and cultural differences, so it generalizes poorly. The typical solution for this problem is to create a table that actually holds the working days (which is generated somewhere just before he year, or calculated in advance if that's feasible), and simply look it up in that.
SELECT DATEADD(DAY,
CASE
(DATEPART(WEEKDAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) + ##DATEFIRST - 1) % 7
WHEN 6 THEN 2
WHEN 7 THEN 1
ELSE 0
END,
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
)
This solution uses ##DATEFIRST to avoid any language issues -- using DATEPART(WEEKDAY, ...) on its own or DATENAME() only works if we assume a specific region.
If you have more flexibility in your SELECT statement, you might be able to use something like this:
;With Daterange As
(
Select DateAdd(Month, DateDiff(Month, 0, GetDate()), 0) As Date Union All
Select DateAdd(Day, 1, Date) As Date
From DateRange
Where Date < DateAdd(Day, 6, DateAdd(Month, DateDiff(Month, 0, GetDate()), 0))
)
Select Convert(Date, Min(Date)) FirstBusinessDay
From Daterange
Where DatePart(WeekDay, Date) Not In (7, 1)
Try this.
SELECT CASE
WHEN Datename(dw, Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())) = 'Saturday' THEN Dateadd(dd, -Datepart(dd, Getdate()) + 3, Getdate())
WHEN Datename(dw, Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())) = 'Sunday' THEN Dateadd(dd, -Datepart(dd, Getdate()) + 2, Getdate())
ELSE Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())
END
Explanation :
Find the first day of the month.
Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())
Then check the day of the previous date by using Datename function.
Datename(dw, Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate()))
If the Datename is Saturday the add 2 days to the first day of the month . if it is sunday then add 1 day to the first day of the month else get the first day of the month

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;