Every 3rd Friday of the Month

  • I'm trying to find every 3rd friday of the month

    The Following code retruns for the current month

    SELECT

    CONVERT(CHAR(10),

    DATEADD(wk,2,(CURRENT_TIMESTAMP -

    Day(CURRENT_TIMESTAMP)+1)+(6-DATEPART(dw,(CURRENT_TIMESTAMP -

    Day(CURRENT_TIMESTAMP)+1)))),

    121)

    if the current day is passed the 3rd friday of the month , I need to show them the next month's 3rd Friday date

    Thanks

  • What does your requirement say if the day passed is between the third Saturday of the month and the last day of the month?

    Ooops, misread your comment "current day passed is" vs "current day is passed".

    There are no special teachers of virtue, because virtue is taught by the whole community.
    --Plato

  • You should be able to accomplish what you want by using a CASE statement. Psuedocode as follows.

    SELECT CASE WHEN current_timestamp > (your 3rd FRIDAY of month calculation)

    THEN (altered 3rd FRIDAY of a month calculation based on DATEADD(MONTH, +1, currenttimestamp) instead of current_timestamp

    ELSE (your current 3rd FRIDAY of the month calculation)

    END

    Be careful when you use DW in a datepart function as the number that represents a particular day will change based on the value of @@DATEFIRST (Depending on your locale the ordinal position of a day in a week may be different than what you expect). Check books online for SET DATEFIRST and @@DATEFIRST for more info.

    -Mike

  • dosskavi (2/17/2011)


    SELECT

    CONVERT(CHAR(10),

    DATEADD(wk,2,(CURRENT_TIMESTAMP -

    Day(CURRENT_TIMESTAMP)+1)+(6-DATEPART(dw,(CURRENT_TIMESTAMP -

    Day(CURRENT_TIMESTAMP)+1)))),

    121)

    For January 2011, that formula returns the 14th, when the third Friday is on the 21st.

    DECLARE @LoopDate AS DATETIME

    SET @LoopDate = CAST('2011-01-01' AS DATETIME)

    SELECT

    CONVERT(CHAR(10),

    DATEADD(wk,2,(@LoopDate -

    Day(@LoopDate)+1)+(6-DATEPART(dw,(@LoopDate -

    Day(@LoopDate)+1)))),

    121)

    2011-01-14

  • abair34 (2/17/2011)


    SELECT CASE WHEN current_timestamp > (your 3rd week of month calculation)

    THEN (altered 3rd week of a month calculation based on DATEADD(MONTH, +1, currenttimestamp) instead of current_timestamp

    ELSE (your current 3rd week of the month calculation)

    END

    The 3rd Friday of the month of January 2011 is in the 4th week.

  • Sorry by 3rd week of the month I meant 3rd friday of the month!! 🙂 Guilty as charged!

  • Someone like Peter Larsson will probably come up with something simpler, but this works...

    SELECT CASE

    WHEN GETDATE() <= CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))/7*7+4+14 AS DATETIME) --3rd Friday Current Month

    THEN CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))/7*7+4+14 AS DATETIME) --3rd Friday Current Month

    ELSE CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE())+1,0))/7*7+4+14 AS DATETIME) --3rd Friday Next Month

    END

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff Moden (2/17/2011)


    SELECT CASE

    WHEN GETDATE() <= CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))/7*7+4+14 AS DATETIME) --3rd Friday Current Month

    THEN CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))/7*7+4+14 AS DATETIME) --3rd Friday Current Month

    ELSE CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE())+1,0))/7*7+4+14 AS DATETIME) --3rd Friday Next Month

    END

    This appears to report:

    1) The 3rd Friday in April 2011 as the 22nd, when it is the 15th.

    2) The 3rd Friday in July 2011 as the 22nd, when it is the 15th.

  • chris_n_osborne (2/17/2011)


    Jeff Moden (2/17/2011)


    SELECT CASE

    WHEN GETDATE() <= CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))/7*7+4+14 AS DATETIME) --3rd Friday Current Month

    THEN CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))/7*7+4+14 AS DATETIME) --3rd Friday Current Month

    ELSE CAST(DATEDIFF(dd,-3,DATEADD(mm,DATEDIFF(mm,0,GETDATE())+1,0))/7*7+4+14 AS DATETIME) --3rd Friday Next Month

    END

    This appears to report:

    1) The 3rd Friday in April 2011 as the 22nd, when it is the 15th.

    2) The 3rd Friday in July 2011 as the 22nd, when it is the 15th.

    Dang it... you're absolutely correct, Chris. Back to the drawing board. 😛

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • This appears to work, at least for 2010 and 2011 (I verified the dates against the calendar). However, it uses a look-up rather than a calculation.

    BEGIN -- Show each 3rd Friday for 2010 and 2011.

    DECLARE @LoopCounter AS INTEGER

    DECLARE @LoopDate AS DATETIME

    SET @LoopCounter = 1

    SET @LoopDate = CAST('2010-01-28' AS DATETIME) -- Whatever Date is Passed (month 1 for convenience)

    SET @LoopDate -- Set @LoopDate to the 1st of the month.

    = CAST(CAST(YEAR(@LoopDate) AS VARCHAR(4))

    + '-' +

    CAST(MONTH(@LoopDate) AS VARCHAR(2))

    + '-' +

    CAST('01' AS VARCHAR(2)) AS DATETIME)

    WHILE @LoopCounter <= 24

    BEGIN

    SELECT @LoopDate

    ,CASE -- Determine the 3rd Friday based on the first day of the month.

    WHEN DATEPART(dw, @LoopDate) = 1 THEN 20

    WHEN DATEPART(dw, @LoopDate) = 2 THEN 19

    WHEN DATEPART(dw, @LoopDate) = 3 THEN 18

    WHEN DATEPART(dw, @LoopDate) = 4 THEN 17

    WHEN DATEPART(dw, @LoopDate) = 5 THEN 16

    WHEN DATEPART(dw, @LoopDate) = 6 THEN 15

    WHEN DATEPART(dw, @LoopDate) = 7 THEN 21

    END AS ThirdFriday

    SET @LoopCounter = @LoopCounter + 1

    SET @LoopDate = DATEADD(month, 1, @LoopDate)

    END

    END

    go

  • Sometimes I just overlook the obvious. Thanks for the hint, Chris. I'll see if I can do it with a formula.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • try thisDECLARE @Date DATETIME

    SELECT @Date = '2011-01-01'

    SELECT Date FROM (

    SELECT Number

    , DATEADD(DAY, number, @Date) AS DATE

    , ROW_NUMBER() OVER (PARTITION BY MONTH(DATEADD(DAY, number, @Date)), YEAR(DATEADD(DAY, number, @Date))

    ORDER BY DATEADD(DAY, number, @Date)) AS ROW

    FROM master..spt_values

    WHERE TYPE = 'p'

    AND DATENAME(DW, DATEADD(DAY, number, @Date)) = 'Friday')A

    WHERE ROW = 3

    ORDER BY DATE

  • Fantastic, Kumar!

  • No doubt about it... both of those pieces of code find the 3rd Friday of each month. But that's only the first part of the problem. If we look back at the original post...

    dosskavi (2/17/2011)


    I'm trying to find every 3rd friday of the month

    The Following code retruns for the current month

    SELECT

    CONVERT(CHAR(10),

    DATEADD(wk,2,(CURRENT_TIMESTAMP -

    Day(CURRENT_TIMESTAMP)+1)+(6-DATEPART(dw,(CURRENT_TIMESTAMP -

    Day(CURRENT_TIMESTAMP)+1)))),

    121)

    if the current day is passed the 3rd friday of the month , I need to show them the next month's 3rd Friday date

    Thanks

    The OP already solved the problem of producing the 3rd Friday for the current date but couldn't solve the problem of...

    if the current day is passed [past] the 3rd friday of the month , I need to show them the next month's 3rd Friday date

    This does. The CASE statement formula is where it all happens. Again, someone can likely simplify the formula but it's fast the way it is and requires no lookup table.

    DECLARE @StartYear DATETIME,

    @EndYear DATETIME

    ;

    SELECT @StartYear = '2000',

    @EndYear = '2099'

    ;

    WITH

    cteBuildDates AS

    ( --=== This just builds a hundred years of test dates. It is not a part of the solution

    -- unless the OP decides to use it to build a Calendar table for the problem.

    SELECT TOP (DATEDIFF(dd,@StartYear,DATEADD(yy,1,@EndYear)))

    CurrentDate = DATEADD(dd, ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1,@StartYear)

    FROM sys.All_Columns ac1

    CROSS JOIN sys.All_Columns ac2

    ) --=== Note that -2 is a Saturday. The CASE statement solves the actual problem with no

    -- character based conversions, does not rely on @@DATEFIRST (dw parts of DATEPART),

    -- and requires no lookup table with additional logic to find the NEXT 3rd Friday.

    -- Hat's off to Chris for the hint about the "offset" for the first of the month.

    SELECT CurrentDate,

    DATENAME(dw,CurrentDate) AS Dow,

    CASE

    WHEN CurrentDate <= DATEADD(mm,DATEDIFF(mm,0,CurrentDate),0) --First of CurrentMonth

    + (20-(DATEDIFF(dd,-2,DATEADD(mm,DATEDIFF(mm,0,CurrentDate),0))%7)) --Offset

    THEN DATEADD(mm,DATEDIFF(mm,0,CurrentDate),0) --First of Current Month

    + (20-(DATEDIFF(dd,-2,DATEADD(mm,DATEDIFF(mm,0,CurrentDate),0))%7)) --Offset

    ELSE DATEADD(mm,DATEDIFF(mm,0,CurrentDate)+1,0) --First of Next Month

    + (20-(DATEDIFF(dd,-2,DATEADD(mm,DATEDIFF(mm,0,CurrentDate)+1,0))%7)) --Offset

    END AS Next3rdFriday

    FROM cteBuildDates

    ;

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Surprised that no one has mentioned using a calendar table so far.

    http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html

    Makes it all pretty simple.



    Clear Sky SQL
    My Blog[/url]

Viewing 15 posts - 1 through 15 (of 25 total)

You must be logged in to reply to this topic. Login to reply