views:

1653

answers:

6

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

+1  A: 

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://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%5FID=99696

JonH
I have alwyas been scare of using a table to stored dates such as these. Holidays are fine as we can localize them, but weekends?
astander
+1  A: 

You can use DATENAME to determine the day you want, i might recomend a small loop to move the date from the 01 of the month in question to get to the first sunday.

so lets try

DECALRE @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).

astander
+2  A: 

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
Charles Bretana
Very nice. Much more compact. How could this be adapted to select, let's say ... the first Wednesday?
Nissan Fan
You would change the %7 to a %3
Anthony
Modulus! Of course. Do you know of an easy way to make it do the 2nd Tuesday of a month for example? Great little function.
Nissan Fan
Here's a link to a more general function. You can use Charles's expression for the required "first of this month" input parameter:http://groups.google.com/group/microsoft.public.sqlserver.programming/browse_thread/thread/664155274229d00b/b5203188f97ee7e9
Steve Kass
Right, the first of next month is DateAdd(Month, 1+DateDiff(Month, 0, @D), 0)
Charles Bretana
A: 

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
Nissan Fan
A: 

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.

Anthony
A: 

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;
Steve Kass