Set datefirst dynamically by the first day of the year - sql

I have fallen a problem to set date first into my SQL query. Here is the code below where I have set by using IF, Else IF. But I need one sql statement not IF, Else IF.
DECLARE #CurrentDate DATE, #FirstDayOfWeek INT
SELECT #CurrentDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
SELECT #FirstDayOfWeek = DATEPART(DW,#CurrentDate)
IF #FirstDayOfWeek = 6
SET DATEFIRST 5; --friday
ELSE IF #FirstDayOfWeek = 7
SET DATEFIRST 6; --sunday
--AND SO ON

The result of DATEPART(DW, . . .) depends on the current value of ##DATEFIRST, so you need to take that into account when setting the new value of ##DATEFIRST. The simplest thing would be to set ##DATEFIRST back to 1, get the current day of the week, and then set ##DATEFIRST to that.
By the way, if you just want the date of a date-time, you can just cast it to DATE. Ultimately, though, there's no need to convert the date-time to a date, because the result of DATEPART(DW, . . .) will be the same either way.
DECLARE #CurrentDate DATE, #CurrentDayOfWeek INT
SET #CurrentDate = CAST(GETDATE() AS DATE)
SET DATEFIRST 1 -- normalize first day of week
SET #CurrentDayOfWeek = DATEPART(DW, #CurrentDate)
SET DATEFIRST #CurrentDayOfWeek
Or
DECLARE #CurrentDayOfWeek INT
SET DATEFIRST 1 -- normalize first day of week
SET #CurrentDayOfWeek = DATEPART(DW, GETDATE())
SET DATEFIRST #CurrentDayOfWeek
Example:
DECLARE #CurrentDayOfWeek INT
SET DATEFIRST 1 -- normalize first day of week to Monday
SET #CurrentDayOfWeek = DATEPART(DW, '2016-01-01') -- a Friday, which will be 5 because first day of week is currently 1
SET DATEFIRST #CurrentDayOfWeek -- first day of week is now 5 (Friday)

I know your question mentions DATEFIRST, but is there any reason you don't just calculate it based on how many days it has been since the first of the year?
SELECT ((DATEPART(DY, GETDATE()) - 1) % 7) + 1
old answer:
Just got to mention that if DATEFIRST has been changed from the default of 7, this will no longer work since DATEPART(dw,...) will return a different value. The value used with SET DATEFIRST is always 1 = Monday, 7 = Sunday, etc. You can always to a SET DATEFIRST 7 ahead of time...
Basically what you are doing is subtracting 1 and rolling back over to 7 if you hit 0. You can just use the mod operator (%) for that:

See if this works for you
DECLARE #CurrentDate DATETIME, #FirstDayOfWeek INT
SELECT #CurrentDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
SELECT #FirstDayOfWeek = DATEPART(DW,#CurrentDate)
SELECT #FirstDayOfWeek = (SELECT CASE #FirstDayOfWeek
WHEN 6 THEN 5
WHEN 7 THEN 6
END )
SET DATEFIRST #FirstDayOfWeek

Related

Returning Database values dependent on days not dates

Hi I'm trying to get a database to return some values, specifically, I need to return every invoice which is dated between the previous Monday to Sunday.
The reason for this is that this query will be ran on varying days, eg I need to return the results for the week Monday 5th August - Sunday 11th August at some point in the following week (12th - 18th).
I originally had this set up as a simple WHERE:
[WHERE TaxDate >= (GETDATE() - 7)]
because the invoices were done every monday so it worked itself out, but now they could be done any day of the following week. Are there any functions that I can use to do this?
Thanks
Look at the datepart function with the day of week parameter:
WHERE Datepart(dw, TaxDate) = 2
declare #currentdow int
declare #delta int
declare #startdate datetime
declare #endtime datetime
set #delta = 0
set #startofweek = DatePart(dw, getDate())
while #scurrentdow <> 2
begin
set #delta = #delta + 1
set #currentdow = #currentdow - 1
if #currentdow < 1
begin
set #currentdow = 7
end
end
set #startdate = DateSubtract(day,GetDate(), delta)
set #enddate = DateAdd(day, #startdate, 6)
long winded, but close I think.

How to get Previous business day in a week with that of current Business Day using sql server

i have an ssis Package which runs on business days (mon-Fri). if i receive file on tuesday , background(DB), it takes previous business day date and does some transactions. If i run the job on friday, it has to fetch mondays date and process the transactions.
i have used the below query to get previous business date
Select Convert(varchar(50), Position_ID) as Position_ID,
TransAmount_Base,
Insert_Date as InsertDate
from tblsample
Where AsOfdate = Dateadd(dd, -1, Convert(datetime, Convert(varchar(10), '03/28/2012', 101), 120))
Order By Position_ID
if i execute this query i'll get the results of yesterdays Transactios. if i ran the same query on monday, it has to fetch the Fridays transactions instead of Sundays.
SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
I prefer to use DATENAME for things like this over DATEPART as it removes the need for Setting DATEFIRST And ensures that variations on time/date settings on local machines do not affect the results. Finally DATEDIFF(DAY, 0, GETDATE()) will remove the time part of GETDATE() removing the need to convert to varchar (much slower).
EDIT (almost 2 years on)
This answer was very early in my SO career and it annoys me everytime it gets upvoted because I no longer agree with the sentiment of using DATENAME.
A much more rubust solution would be:
SELECT DATEADD(DAY, CASE (DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7
WHEN 1 THEN -2
WHEN 2 THEN -3
ELSE -1
END, DATEDIFF(DAY, 0, GETDATE()));
This will work for all language and DATEFIRST settings.
This function returns last working day and takes into account holidays and weekends. You will need to create a simple holiday table.
-- =============================================
-- Author: Dale Kilian
-- Create date: 2019-04-29
-- Description: recursive function returns last work day for weekends and
-- holidays
-- =============================================
ALTER FUNCTION dbo.fnGetWorkWeekday
(
#theDate DATE
)
RETURNS DATE
AS
BEGIN
DECLARE #importDate DATE = #theDate
DECLARE #returnDate DATE
--Holidays
IF EXISTS(SELECT 1 FROM dbo.Holidays WHERE isDeleted = 0 AND #theDate = Holiday_Date)
BEGIN
SET #importDate = DATEADD(DAY,-1,#theDate);
SET #importDate = (SELECT dbo.fnGetWorkWeekday(#importDate))
END
--Satruday
IF(DATEPART(WEEKDAY,#theDate) = 7)
BEGIN
SET #importDate = DATEADD(DAY,-1,#theDate);
SET #importDate = (SELECT dbo.fnGetWorkWeekday(#importDate))
END
--Sunday
IF(DATEPART(WEEKDAY,#theDate) = 1)
BEGIN
SET #importDate = DATEADD(DAY,-2,#theDate);
SET #importDate = (SELECT dbo.fnGetWorkWeekday(#importDate))
END
RETURN #importDate;
END
GO
Then how about:
declare #dt datetime='1 dec 2012'
select case when 8-##DATEFIRST=DATEPART(dw,#dt)
then DATEADD(d,-2,#dt)
when (9-##DATEFIRST)%7=DATEPART(dw,#dt)%7
then DATEADD(d,-3,#dt)
else DATEADD(d,-1,#dt)
end
The simplest solution to find the previous business day is to use a calendar table with a column called IsBusinessDay or something similar. The your query is something like this:
select max(BaseDate)
from dbo.Calendar c
where c.IsBusinessDay = 0x1 and c.BaseDate < #InputDate
The problem with using functions is that when (not if) you have to create exceptions for any reason (national holidays etc.) the code quickly becomes unmaintainable; with the table, you just UPDATE a single value. A table also makes it much easier to answer questions like "how many business days are there between dates X and Y", which are quite common in reporting tasks.
You can easily make this a function call, adding a second param to replace GetDate() with whatever date you wanted.
It will work for any day of the week, at any date range, if you change GetDate().
It will not change the date if the day of week is the input date (GetDate())
Declare #DayOfWeek As Integer = 2 -- Monday
Select DateAdd(Day, ((DatePart(dw,GetDate()) + (7 - #DayOfWeek)) * -1) % 7, Convert(Date,GetDate()))
More elegant:
select DATEADD(DAY,
CASE when datepart (dw,Getdate()) < 3 then datepart (dw,Getdate()) * -1 + -1 ELSE -1 END,
cast(GETDATE() as date))
select
dateadd(dd,
case DATEPART(dw, getdate())
when 1
then -2
when 2
then -3
else -1
end, GETDATE())
thanks for the tips above, I had a slight variant on the query in that my user needed all values for the previous business date. For example, today is a Monday so he needs everything between last Friday at midnight through to Saturday at Midnight. I did this using a combo of the above, and "between", just if anyone is interested. I'm not a massive techie.
-- Declare a variable for the start and end dates.
declare #StartDate as datetime
declare #EndDate as datetime
SELECT #StartDate = DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
select #EndDate = #StartDate + 1
select #StartDate , #EndDate
-- Later on in the query use "between"
and mydate between #StartDate and #EndDate

How to get Saturday's Date (Or any other weekday's Date)- SQL Server

How to get Saturday's Date. I have today's date with me.
GETDATE()
How to do this.
For eg. TODAY is 08-08-2011
I want output as 08-13-2011
This is a function that will return the next Saturday if you call it like this:
SELECT dbo.fn_Get_NextWeekDay('2011-08-08', 6)
The "6" comes from the list of possible values you can set for DATEFIRST.
You can get any other day of the week by changing the second parameter accordingly.
This is the function:
IF OBJECT_ID('dbo.fn_Get_NextWeekDay') IS NOT NULL
DROP FUNCTION dbo.fn_Get_NextWeekDay
GO
CREATE FUNCTION dbo.fn_Get_NextWeekDay(
#aDate DATETIME
, #dayofweek INT
/*
#dw - day of the week
1 - Monday
2 - Tuesday
3 - Wednesday
4 - Thursday
5 - Friday
6 - Saturday
7 - Sunday
*/
)
RETURNS DATETIME
AS
/*
SELECT dbo.fn_Get_NextWeekDay('2011-08-08', 6)
SELECT dbo.fn_Get_NextWeekDay('2011-08-08', 1)
*/
BEGIN
RETURN
DATEADD(day
, ( #dayofweek + 8 - DATEPART(dw, #aDate) - ##DATEFIRST ) % 7
, #aDate
)
END
GO
[EDIT]
This might be another solution. This should work in any language:
IF OBJECT_ID('dbo.fn_NextWeekDay') IS NOT NULL
DROP FUNCTION dbo.fn_NextWeekDay
GO
CREATE FUNCTION dbo.fn_NextWeekDay(
#aDate DATE
, #dayofweek NVARCHAR(30)
)
RETURNS DATE
AS
/*
SELECT dbo.fn_NextWeekDay('2016-12-14', 'fri')
SELECT dbo.fn_NextWeekDay('2016-03-15', 'mon')
*/
BEGIN
DECLARE #dx INT = 6
WHILE UPPER(DATENAME(weekday,#aDate)) NOT LIKE UPPER(#dayofweek) + '%'
BEGIN
SET #aDate = DATEADD(day,1,#aDate)
SET #dx=#dx-1
if #dx < 0
BEGIN
SET #aDate = NULL
BREAK
END
END
RETURN #aDate
END
GO
Use DATEPART to get the day of week of today and add the difference to the desired day of week to todays date.
DECLARE #Today date = 'TODAYS-DATE';
DECLARE #TodayNumber int = DATEPART(dw, #Today) -- Get the day number
DECLARE #Saturday date = DATEADD(DAY, (6-#TodayNumber)%7, #Today)
-- Add the number of days between today and saturday (the 6th day), modulus 7 to stop you adding negative days
Hope that helps!
Use a Calendar table (table with one row per date):
SELECT MIN(DateValue) DateValue
FROM Calendar
WHERE DateValue >= CURRENT_TIMESTAMP
AND DayOfWeek = 'Saturday';
Another approach to this takes two steps, but might be more readable (look ma, no modulus):
Go back to last saturday: DATEADD(DAY, -1 * datepart(weekday, GETDATE()), getdate())
Then, add on a week: DATEADD(WEEK, 1, #lastSaturday, getdate()))
The whole thing:
declare #today DATETIME = GETDATE()
declare #lastSaturday DATETIME = DATEADD(DAY, -1 * datepart(weekday, #today), #today)
declare #nextSaturday DATETIME = DATEADD(WEEK, 1, #lastSaturday)
Or, if you're ok with #today being GETDATE(), you can do the calculation all at once:
SELECT DATEADD(WEEK, 1, DATEADD(DAY, -1 * datepart(weekday, GETDATE()), getdate()))
Checkout the SQL DATEADD function.
DATEADD (Transact-SQL)
Which you can use this along with DATEPART function to return the correct date.
DATEPART (Transact-SQL)
Try this :
SET DATEFIRST 7
DECLARE #d DATETIME
SET #d = '2011-08-08' --GETDATE()
SELECT NEXT_SAT = DATEADD(day, (7 + ##DATEFIRST - DATEPART(dw, #d)) % 7, #d )
declare #Curdate date=( SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(),'+05:30') )
declare #nextsaturdaydate date=(select dateadd(d, 7-datepart(WEEKDAY, #CurDate),#Curdate))
select #nextsaturdaydate

Find the Friday that a particular date is "closest" to in T-Sql

I'm looking for an elegant simple way to determine the date of the Friday that is closest to a particular date. Any ideas?
The trick is to determine how many days away the closest Friday is from the offered date. To help, look at an entire week and the number of days away from the closest Friday:
Sunday -2
Monday -3
Tuesday 3
Wednesday 2
Thursday 1
Friday 0
Saturday -1
Now you need a formula to return these results. Because Sunday and Monday follow a different pattern from the other days of the week, two formulas are needed.
First, here is the one for Sunday and Monday. It adds 1 to the day of the week value then takes the negative to apply to the date add. For example, Monday has a default of 2 as the day of the week value. (2 + 1) * -1 = -3. -3 + Monday = Friday.
Tuesday - Saturday use similar arithmetic: The dates return the day of week values 3, 4, 5, 6, & 7. We need date add values of 3,2,1,0,-1 respectively. The formula to get this is DW * -1 + 6.
DECLARE #Date AS datetime
SET #Date = '3/1/2010'
SELECT
CASE
WHEN DATEPART(dw, #Date) <= 2
THEN DATEADD(d, -1 * (DATEPART(dw, #Date) + 1), #Date)
ELSE DATEADD(d, DATEPART(dw, #Date) * -1 + 6, #Date)
END AS NearestFriday
This returns a closest Friday in the future:
SELECT DATEADD(day, 6 - (DATEDIFF(day, '01/01/2010', #mydate) - 1) % 7, #mydate)
You have to slide the beginning of the week (using DATEFIRST) so that you get Tuesday becomes the middle of the week and then you just add the number of days to go to the closest Friday,.
SET NOCOUNT ON
SET DATEFIRST 3
Declare #DateValue DateTime
SET #DateValue = '1/1/2010'
While #DateValue < '2/1/2011'
BEGIN
PRINT DateAdd (Day, 3 - DatePart (dw, #DateValue), #DateValue)
SET #DateValue = #DateValue + 1
END
if you need to find the closest (past or future) Friday, try this:
DECLARE #StartDate datetime
,#EndDate datetime
,#BeforeDate datetime
SET #StartDate='2010-3-1'---<<<given date, Monday, closest should be '2010-2-26'
SET #EndDate=#StartDate+8
SET #BeforeDate=#StartDate-8
;with AllDates AS
(
SELECT #StartDate AS DateOf, 1 as TypeOf,DATENAME(weekday,#StartDate) AS WeekDayOf, ABS(DATEDIFF(day,#StartDate,#StartDate)) AS DifferenceOf
UNION ALL
SELECT DateOf+1 AS DateOf,2 AS TypeOf,DATENAME(weekday,DateOf+1 ) AS WeekDayOf, ABS(DATEDIFF(day,#StartDate,DateOf+1)) AS DifferenceOf
FROM AllDates
WHERE DateOf<#EndDate-1 AND TypeOf IN (1,2)
UNION ALL
SELECT DateOf-1 AS DateOf,3 AS TypeOf,DATENAME(weekday,DateOf-1 ) AS WeekDayOf, ABS(DATEDIFF(day,#StartDate,DateOf-1)) AS DifferenceOf
FROM AllDates
WHERE DateOf>#BeforeDate-1 AND TypeOf IN (1,3)
)
SELECT TOP 1 DateOf
FROM AllDates
WHERE WeekDayOf='Friday'
ORDER BY DifferenceOf
OUTPUT:
DateOf
-----------------------
2010-02-26 00:00:00.000
(1 row(s) affected)
SQL Server solution as a user-defined function. Will round not just to the nearest Friday, but to the nearest of any weekday (1-7) you specify:
CREATE FUNCTION RoundToNearestWeekday (
--Give this function a date, and the number of the weekday you want to round to the nearest of
#DateInput date, --Date you want to round
#ToWeekdayNumber tinyint --1 = round to nearest Sunday, 2 = round to nearest Monday, etc.
)
RETURNS date
AS
BEGIN
DECLARE #Offset tinyint, #LowNumber smallint, #HighNumber smallint, #NewDate date
SET #Offset = (#ToWeekdayNumber + 3)%7
SET #LowNumber = #Offset-3
SET #HighNumber = #Offset+4
SET #NewDate = dateadd(day,CASE WHEN datepart(weekday,#DateInput) <= #Offset THEN #LowNumber ELSE #HighNumber END - datepart(weekday,#DateInput),#DateInput)
RETURN #NewDate
END

Get first Sunday of next month using T-SQL

Looking for a way to get the date in the format "11/1/2009", which would be the first sunday of next month. I want to run this query after the first sunday in october to get the first sunday of the upcoming month. What is the best method to accomplish this with a T-SQL query?
Thanks
try this:
Declare #D Datetime
Set #D = [Some date for which you want the following months' first sunday]
Select DateAdd(day, (8-DatePart(weekday,
DateAdd(Month, 1+DateDiff(Month, 0, #D), 0)))%7,
DateAdd(Month, 1+DateDiff(Month, 0, #D), 0))
EDIT Notes:
The first of next Month is given by the expression:
DateAdd(Month, 1+DateDiff(Month, 0, #D), 0)
or by:
which can be modified to give the first of the month two months from now by changing the 1 to a 2:
DateAdd(Month, 2+DateDiff(Month, 0, #D), 0)
EDIT: In response to #NissanFan, and #Anthony: to modify this to return the first Monday Tuesday Wednesday, etc, change the value 8 to a 9, 10, 11, etc....
Declare #Sun TinyInt Set #Sun = 8
Declare #Mon TinyInt Set #Mon = 9
Declare #Tue TinyInt Set #Tue = 10
Declare #Wed TinyInt Set #Wed = 11
Declare #Thu TinyInt Set #Thu = 12
Declare #Fri TinyInt Set #Fri = 13
Declare #Sat TinyInt Set #Sat = 14
Declare #D Datetime, #FONM DateTime -- FirstofNextMonth
Set #D = [Some date for which you want the following months' first sunday]
Set #FONM = DateAdd(Month, 1+DateDiff(Month, 0, #D),0)
Select
DateAdd(day, (#Sun -DatePart(weekday, #FONM))%7, #FONM) firstSunInNextMonth,
DateAdd(day, (#Mon -DatePart(weekday, #FONM))%7, #FONM) firstMonInNextMonth,
DateAdd(day, (#Tue -DatePart(weekday, #FONM))%7, #FONM) firstTueInNextMonth,
DateAdd(day, (#Wed -DatePart(weekday, #FONM))%7, #FONM) firstWedInNextMonth,
DateAdd(day, (#Thu -DatePart(weekday, #FONM))%7, #FONM) firstThuInNextMonth,
DateAdd(day, (#Fri -DatePart(weekday, #FONM))%7, #FONM) firstFriInNextMonth,
DateAdd(day, (#Sat -DatePart(weekday, #FONM))%7, #FONM) firstSatInNextMonth
Just an FYI rather then coming up with some code to do this how about using a calendar table.
Take a look at this: http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html
This also may help:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=99696
Here is a query to get first working day of next month
DECLARE #DAYOFWEEK INT,#ReminderDate DateTime
SET #DAYOFWEEK = DATEPART( WEEKDAY,DateAdd(D,- Day(GetDate())+1, DATEADD(M,1,GetDate())) )
Print #DAYOFWEEK
If #DAYOFWEEK = 1
Set #ReminderDate = DateAdd(D,- Day(GetDate())+2, DATEADD(M,1,GetDate()))
Else If #DAYOFWEEK =7
Set #ReminderDate = DateAdd(D,- Day(GetDate())+3, DATEADD(M,1,GetDate()))
Else
Set #ReminderDate = DateAdd(D,- Day(GetDate())+1, DATEADD(M,1,GetDate()))
Print #ReminderDate
Reference taken from this blog:
SQL Server 2012 introduced one new TSQL EOMONTH to return the last day of the month that contains the specified date with an optional offset.
CREATE TABLE tbl_Test_EOMONTH
(
SampleDate DATETIME
)
GO
INSERT INTO tbl_Test_EOMONTH VALUES ('2015-12-20')
INSERT INTO tbl_Test_EOMONTH VALUES ('2015-11-08')
INSERT INTO tbl_Test_EOMONTH VALUES ('2015-10-16')
INSERT INTO tbl_Test_EOMONTH VALUES ('2015-09-26')
INSERT INTO tbl_Test_EOMONTH VALUES ('2016-01-31')
GO
SELECT
DATEADD(DAY,8-DATEPART(WEEKDAY,DATEADD(DAY,0,EOMONTH([SampleDate])))
,EOMONTH([SampleDate])) AS FirstSunday_ofTheNextMonth
FROM tbl_Test_EOMONTH
GO
You can use DATENAME to determine the day you want, I might recommend a loop to move the date from the 01 of the month in question to get to the first sunday.
So lets try:
DECLARE #DateTime DATETIME
Set to the date to start off with, then add 1 day until you find what you are looking for. Use datename with dw...
We have used this to determine weekends, but holidays will be a problem, where we use a table to store that.
Try this code as a function:
-- Variables
DECLARE #DATE DATETIME
DECLARE #DAY INT
DECLARE #DAYOFWEEK INT
DECLARE #TESTDATE DATETIME
-- Set
SET #TESTDATE = GETDATE()
SET #DATE = DATEADD( MONTH, 1, #TESTDATE )
SET #DAY = DATEPART( DAY, #TESTDATE )
SET #DATE = DATEADD( DAY, -#DAY + 1, #DATE )
SET #DAYOFWEEK = DATEPART( WEEKDAY, #DATE )
IF #DAYOFWEEK > 1
BEGIN
SET #DAYOFWEEK = 8 - #DAYOFWEEK
END
ELSE
BEGIN
SET #DAYOFWEEK = 0
END
SET #DATE = DATEADD( DAY, #DAYOFWEEK, #DATE )
-- Display
PRINT #TESTDATE
PRINT #DAY
PRINT #DAYOFWEEK
PRINT #DATE
Here is the non-system specific way to determine the first Sunday of the following month:
First, get the current month and add one month.
Next, set the date of that variable to be on the first.
Next, find the day value of that date (let's assume Mondays are 1 and Sundays are 7).
Next, subtract the day value of the 1st of the month from the day value of Sunday (7).
You now have the number of days between the first of the month and the first Sunday. You could then add that to the date variable to get the first Sunday, or, since we know the first of the month is 1, you could just add one to the difference (found in that last step above) and that is the date of the first Sunday. (You have to add one because it's subtracting and thus if the first of the given month IS Sunday, you'd end up with 0).
I have been looking through the T-SQL documentation and it is not at all intuitive as to how how you would use my method, but you will need the concept of "day of week number" to make it work no matter what.
This would be simplest with an auxiliary calendar table. See this link, for example.
However, it can be done without one, though it's rather tricky. Here I assume you want the first future date that is the first Sunday of a month. I've written this with a variable #now for - well - now, so it's easier to test. It might be possible to write more simply, but I think this has a better chance of being correct than quickly-written simpler solutions. [Corrected by adding DAY(d) < 8]
SET #now = GETDATE();
WITH Seven(i) AS (
SELECT -1 UNION ALL SELECT 0 UNION ALL SELECT 1
UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6
), Candidates(d) AS (
SELECT DATEADD(WEEK,i+DATEDIFF(WEEK,'19000107',#now),'19000107')
FROM Seven
)
SELECT TOP (1) d AS SoonestFutureFirstSunday
FROM Candidates
WHERE DAY(d) < 8 AND MONTH(d) >= MONTH(#now)
AND (MONTH(d) > MONTH(#now) OR DAY(d) > DAY(#now))
ORDER BY d; ORDER BY d;
I reckon that the answer is this
SELECT DATEADD(Month, DATEDIFF(Month, 0, GETDATE()) + 1, 0) + 6 - (DATEPART(Weekday,
DATEADD(Month,
DATEDIFF(Month,0, GETDATE()) + 1, 0))
+ ##DateFirst + 5) % 7 --FIRST sunday of following month