Simple SQL challenge - who can solve

  • Hi,

    Simple little requirement.

    Need to display first date of each of the 12 months prior to current date, i.e. "Last Twelve Months" for reporting purposes.

    i.e. today is 10th May 2016 so we need this:

    2016-05-01 00:00:00.000

    2016-04-01 00:00:00.000

    2016-03-01 00:00:00.000

    2016-02-01 00:00:00.000

    2016-01-01 00:00:00.000

    2015-12-01 00:00:00.000

    2015-11-01 00:00:00.000

    2015-10-01 00:00:00.000

    2015-09-01 00:00:00.000

    2015-08-01 00:00:00.000

    2015-07-01 00:00:00.000

    2015-06-01 00:00:00.000

    I have some possible solutions in the pipeline but feel there's probably a simpler way out there

  • DuncEduardo (5/11/2016)


    Hi,

    Simple little requirement.

    Need to display first date of each of the 12 months prior to current date, i.e. "Last Twelve Months" for reporting purposes.

    i.e. today is 10th May 2016 so we need this:

    2016-05-01 00:00:00.000

    2016-04-01 00:00:00.000

    2016-03-01 00:00:00.000

    2016-02-01 00:00:00.000

    2016-01-01 00:00:00.000

    2015-12-01 00:00:00.000

    2015-11-01 00:00:00.000

    2015-10-01 00:00:00.000

    2015-09-01 00:00:00.000

    2015-08-01 00:00:00.000

    2015-07-01 00:00:00.000

    2015-06-01 00:00:00.000

    I have some possible solutions in the pipeline but feel there's probably a simpler way out there

    Is any of your possible solutions a Tally Table[/url]?

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • Tally Table seemed unnecessarily complex - am sure there's something simpler

  • DuncEduardo (5/11/2016)


    Tally Table seemed unnecessarily complex - am sure there's something simpler

    The most efficient methods I know of require a sequence from 1-12. You can call it dog if you like instead of tally table, and you can build it any number of ways. Doesn't change reality though. 😉

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • DuncEduardo (5/11/2016)


    Tally Table seemed unnecessarily complex - am sure there's something simpler

    Seriously? Do you understand what a tally table is? It's nothing more that a table (which could be a view, a function, a cte or a derived table) with a single column of consecutive numbers. It helps you to generate rows, as many as you need. Using a tally table is the only way to get this in a single statement.

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • Select some DATEADD columns from a table is complex?

    There's many more complex methods, but some form of tally table's probably one of the easiest.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • By the looks of it this elementary, is this the real problem?

    😎

  • I'd like to pile on and say a Tally Table is the best performing and most simple solution.

    That said, another high-performing and very simple solution would be one that uses a calendar table.

    "I cant stress enough the importance of switching from a sequential files mindset to set-based thinking. After you make the switch, you can spend your time tuning and optimizing your queries instead of maintaining lengthy, poor-performing code."

    -- Itzik Ben-Gan 2001

  • I've used mixture of "while", "getdate()", "datediff" and for the minute size of it, works well.

    I'd consider tally table for something more substantial, but for the sake of 12 rows containing single column where processing is done daily out-of-hours then I'm not worried about performance to be honest.

  • DuncEduardo (5/11/2016)


    I've used mixture of "while", "getdate()", "datediff" and for the minute size of it, works well.

    I'd consider tally table for something more substantial, but for the sake of 12 rows containing single column where processing is done daily out-of-hours then I'm not worried about performance to be honest.

    I'm pretty sure is not as simple as this.

    SELECT DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-n, 0)

    FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11))x(n);

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • Yes but you've explicitly stated numbers corresponding to calendar months from Jan - Nov. I try to avoid any form of "hard-coding".

    Nice solution though

  • DuncEduardo (5/11/2016)


    Yes but you've explicitly stated numbers corresponding to calendar months from Jan - Nov. I try to avoid any form of "hard-coding".

    Nice solution though

    Luis's solution only has a table with 12 numbers (0 - 11) hardcoded. Substitute a datetime variable for the GETDATE() and change the dates and watch what happens.

  • For what it's worth, this one can be paramaterized in terms of the number of dates returned, and it doesn't require a pre-existing tally table, which might be useful in a scenario where you are querying a database for which you arn't the owner. However, leveraging a system table and ranking function to perform ad-hoc the job of a tally table is a performance hit and makes the code confusing to read.

    select top (12) cast(convert( char(7), dateadd(month,(-row_number()

    over (order by msglangid, error))+1, getdate() ), 121 )+'-01' as date) d

    from master.sys.sysmessages

    order by msglangid, error;

    2016-05-01

    2016-04-01

    2016-03-01

    2016-02-01

    2016-01-01

    2015-12-01

    2015-11-01

    2015-10-01

    2015-09-01

    2015-08-01

    2015-07-01

    2015-06-01

    "Do not seek to follow in the footsteps of the wise. Instead, seek what they sought." - Matsuo Basho

  • Eric M Russell (5/11/2016)


    For what it's worth, this one can be paramaterized in terms of the number of dates returned, and it doesn't require a pre-existing tally table, which might be useful in a scenario where you are querying a database for which you arn't the owner. However, leveraging a system table and ranking function to perform ad-hoc the job of a tally table is a performance hit and makes the code confusing to read.

    Which is why Luis' solution uses the table value constructor to create the sequence.

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • Lynn Pettis (5/11/2016)


    DuncEduardo (5/11/2016)


    Yes but you've explicitly stated numbers corresponding to calendar months from Jan - Nov. I try to avoid any form of "hard-coding".

    Nice solution though

    Luis's solution only has a table with 12 numbers (0 - 11) hardcoded. Substitute a datetime variable for the GETDATE() and change the dates and watch what happens.

    And I can actually get the following code with 7 keystrokes using code snippets. Code snippets are a built-in functionality since SQL Server 2012.

    WITH

    E(n) AS(

    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)

    ),

    E2(n) AS(

    SELECT a.n FROM E a, E b

    ),

    E4(n) AS(

    SELECT a.n FROM E2 a, E2 b

    ),

    cteTally(n) AS(

    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n

    FROM E4

    )

    SELECT n

    FROM cteTally

    It could be even less work if I used a function which would allow me to get a defined range, but I avoid posting udfs in the forums.

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2

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

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