Datetime SQL Programming

  • Kindest All,

    I've these following table structure,

    tbltransaction

    TID | Date_occur

    ----------------------

    1 | 3/21/2006

    2 | 3/24 /2006

    3 | 3/31/2006

    4 | 4/18/2006

    5 | 4/21/2006

    6 | 4/29/2006

    7 | 4/30/2006

    8 | 4/30/2006

    9 | 5/2/2006

    10 | 5/10/2006

    11 | 5/12/2006

    12 | 5/17/2006

    How do i write SQL, to know 'How many transaction happen in Mar, April and May?'. The expected result shown below

    Month | NumberOfTransaction

    ------------------------------

    Mar | 3

    April | 5

    May | 4

    Plz...

  • SELECT DATEPART(mm, Date_occur) AS Month, COUNT(*) as NumberOfTransaction

    FROM tblTransaction

    GROUP BY DATEPART(mm, Date_occur)

    ORDER BY DATEPART(mm, Date_occur) ASC

    That should do it...

  • If you want the months converted from numbers into names, try the following:

    select

    CASE DatePart(month,Date_occur)

       WHEN 1 THEN 'Jan'

       WHEN 2 THEN 'Feb'

       WHEN 3 THEN 'Mar'

       WHEN 4 THEN 'Apr'

       WHEN 5 THEN 'May'

       WHEN 6 THEN 'Jun'

       WHEN 7 THEN 'Jul'

       WHEN 8 THEN 'Aug'

       WHEN 9 THEN 'Sep'

       WHEN 10 THEN 'Oct'

       WHEN 11 THEN 'Nov'

       WHEN 12 THEN 'Dec'

       ELSE cast(DatePart(month,Date_occur) as varchar)

    END as [Month]

    , count(*) as [NumberOfTransactions]

    from tblTransaction

    group by DatePart(month, Date_occur)

    having DatePart(month,Date_occur) in (3,4,5) -- Only need this line if you're only interested in those particular months

    order by DatePart(month,Date_occur)

  • Depending on whether your data will eventually span multiple years you may want to either add DATEPART(year, Date_occur) or add a WHERE condition if it is important to determine which events happened THIS September versus in ALL Septembers, etc.

    If you want the month name rather than the month number, you can either use Ian's CASE statement or DATENAME(month, Date_occur).

    /* Group by year-month */
    SELECT DATEPART(year, Date_occur) AS [Year], DATEPART(month, Date_occur) AS [Month],
         COUNT(*) AS [NumberOfTransactions]
    FROM tblTransaction
    GROUP BY DATEPART(year, Date_occur), DATEPART(month, Date_occur)
    ORDER BY DATEPART(year, Date_occur), DATEPART(month, Date_occur)
    GO
    
    /* Group by month for the selected year only */
    SELECT DATEPART(month, Date_occur) AS [Month],
         COUNT(*) AS [NumberOfTransactions]
    FROM tblTransaction
    WHERE Date_occur >= CONVERT(DATETIME, '2006-01-01') 
      AND Date_occur < CONVERT(DATETIME, '2007-01-01')
    GROUP BY DATEPART(month, Date_occur)
    ORDER BY DATEPART(month, Date_occur)
    GO
    

    --Andrew

  • >>

    select CASE DatePart(month,Date_occur)

       WHEN 1 THEN 'Jan'

       WHEN 2 THEN 'Feb'

       WHEN 3 THEN 'Mar'

       WHEN 4 THEN 'Apr'

       WHEN 5 THEN 'May'

       WHEN 6 THEN 'Jun'

       WHEN 7 THEN 'Jul'

       WHEN 8 THEN 'Aug'

       WHEN 9 THEN 'Sep'

       WHEN 10 THEN 'Oct'

       WHEN 11 THEN 'Nov'

       WHEN 12 THEN 'Dec'

       ELSE cast(DatePart(month,Date_occur) as varchar)

    END as [Month]

    <<

    Anything wrong with

    select

    Left(DateName(month,Date_occur),3) AS [Month]

    ?

  • This should for a selected year

    SELECT  DATENAME(month, Date_Occur) AS [Month],

     COUNT(*) AS [NumberOfTransactions]

    FROM

     tblTransaction

    WHERE

     Date_Occur >= CONVERT(DATETIME, '2006-01-01')  

    AND

     Date_Occur < CONVERT(DATETIME, '2007-01-01')

    GROUP BY

     DATENAME(month, Date_Occur),

     DATEPART(month,Date_Occur)

    ORDER BY

     DATEPART(month,Date_Occur)

    Thx

    Prasad Bhogadi
    www.inforaise.com

  • Ian,

    Nice job at producing the return that the original poster actually asked for... there is one little problem... you cannot include the ELSE clause that you have or you get this...

    Server: Msg 8120, Level 16, State 1, Line 1

    Column 'tblTransaction.Date_Occur' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

    Lisa,

    Yep... there is something wrong with doing it that way... you would also have to include the formula as the object of both the GROUP BY and the ORDER BY... that would cause the output to be generated in alpha order for the month instead or ordinal order...

    select Left(DateName(month,Date_occur),3) AS [Month]
    , count(*) as [NumberOfTransactions]
    from tblTransaction
    group by Left(DateName(month,Date_occur),3)
    order by Left(DateName(month,Date_occur),3)
    Month NumberOfTransactions
    Apr   5
    Mar   3
    May   4
    (3 row(s) affected)

    My rule of thumb is divide-and-conquer... make it work, make it fast, then make it pretty.  In other words, do the math part first and then format the results...

    I use a derived table to do the simple math (thereby keeping the math/code simple) and format the results of that derived table using a very simple outer select (thereby keeping the formatting/code simple).   If you don't want the YEAR in the output, just remove it from the outer select.  Makes for a much simpler GROUP BY and ORDER BY and is much easier to mod the output for whatever reason including the construction of cross-tabs and all.

     SELECT [Year]  = YEAR(d.MonthStart),
            [Month] = LEFT(DATENAME(mm,d.MonthStart),3),
            d.NumberOfTransaction
       FROM (--Derived table "d" does the math, the outer select does the formatting
             SELECT MonthStart          = DATEADD(mm,DATEDIFF(mm,0,Date_Occur),0),
                    NumberOfTransaction = COUNT(*) 
               FROM dbo.tblTransaction
              GROUP BY DATEADD(mm,DATEDIFF(mm,0,Date_Occur),0)
            ) d
      ORDER BY d.MonthStart

    --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)

  • Thank you for explaining your reasoning, Jeff.  I respectfully disagree.

    1. The order will almost always be determined externally to this expression anyway, since unless you can guarantee < 12 months and all in the same calendar year you might as well do your ordering by the real/original date.

    2. *My* rule of thumb is "never embed localizable strings into code" <shrug>.

    As it happens, I do agree with you about doing the formatting and making things pretty only *after* making it work/getting the SQL results.  Since my "final formatting" (as well as final display order) will not be determined by the server in many cases, prettification is not generally the concern or the major responsibility of my sproc.  Efficiency, however, is.

    >L<

  • 1. The order will almost always be determined externally to this expression anyway, since unless you can guarantee < 12 months and all in the same calendar year you might as well do your ordering by the real/original date.

    Don't need to guarantee that they'll all be in the same calendar year with the way I wrote it... it will work for all months of all years because I am, in fact, doing the ordering by the "real/original" date.  Read the code...

    2. *My* rule of thumb is "never embed localizable strings into code" <shrug>.

    I'm not sure what you mean by "never embed localizable strings into code"... What localizable strings have I embedded?

    Also, in case anyone's interested, here's the basis for making this into a proc with a parameter for the year...

    DECLARE @pYear INT
        SET @pYear = 2006
     SELECT [Year]  = YEAR(d.MonthStart),
            [Month] = LEFT(DATENAME(mm,d.MonthStart),3),
            d.NumberOfTransaction
       FROM (--Derived table "d" does the math, the outer select does the formatting
             SELECT MonthStart          = DATEADD(mm,DATEDIFF(mm,0,Date_Occur),0),
                    NumberOfTransaction = COUNT(*) 
               FROM dbo.tblTransaction
              WHERE Date_Occur >= DATEADD(yy,@pYear-1900,0)
                AND Date_Occur <  DATEADD(yy,@pYear-1900+1,0)
              GROUP BY DATEADD(mm,DATEDIFF(mm,0,Date_Occur),0)
            ) d
      ORDER BY d.MonthStart
     

    --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, I did read your code.  I know that you are handling the order by adding the year. I think you missed my point; you shouldn't need to compensate, because you have the original date in the first place.

    The localizable strings... you are kidding, right?... were in the code I quoted when I wrote my original message:

    >>

    select CASE DatePart(month,Date_occur)

       WHEN 1 THEN 'Jan'

       WHEN 2 THEN 'Feb'

       WHEN 3 THEN 'Mar'

       WHEN 4 THEN 'Apr'

       WHEN 5 THEN 'May'

       WHEN 6 THEN 'Jun'

       WHEN 7 THEN 'Jul'

       WHEN 8 THEN 'Aug'

       WHEN 9 THEN 'Sep'

       WHEN 10 THEN 'Oct'

       WHEN 11 THEN 'Nov'

       WHEN 12 THEN 'Dec'

       ELSE cast(DatePart(month,Date_occur) as varchar)

    END as [Month]

    <<

    When I wrote to you, I was explaining why I bothered contributing to the thread and why this matters to me. 

    Although I do a huge amount of date math, and although code efficiency matters, a simple efficiency issue (for example, an unnecessary CASE statement or even somebody who prefers to use YEAR() and MONTH() functions to order records rather than the date) would not have been enough for me to write.

    What prompted me to volunteer a different solution was the code you see above.

    Everybody has their rules of thumb and their priorities.  Smoothly-localizable code is one of mine. (Rooting out hard-coded strings is a related one.)

    As I said before, ORDER is not one of my priorities, since my date-related presentations are mostly going to end up in SSML or XLSX anyway. The sproc can handle calculating columns efficiently, anything beyond that is left to mid-tier ordering (by the component that's going to extrude the SSML). And generally the user is going to be able to re-sort in the end-level interface. 

    But I have no problem with ORDER being a priority for you -- however you choose to handle it.

    >L<

     

  • Ok, Lisa... you just assumed that I knew you were talking about the "other" code in your rule of thumb and I thought you were talking about the code I submitted which didn't come near a localized string.  I agree that localized strings like in the "other" should not be included in code.

    I didn't add the year to the mathematical process... it was already there because I handle the data as datetimes (as they should be) instead of just months.  Remove the year from the outer select and it will still work correctly provided that you add the where clause (as I did in the last post) to isolate a single year as you would for any of the posted code.  Like this...

    DECLARE @pYear INT
        SET @pYear = 2006
     SELECT [Month] = LEFT(DATENAME(mm,d.MonthStart),3),
            d.NumberOfTransaction
       FROM (--Derived table "d" does the math, the outer select does the formatting
             SELECT MonthStart          = DATEADD(mm,DATEDIFF(mm,0,Date_Occur),0),
                    NumberOfTransaction = COUNT(*) 
               FROM dbo.tblTransaction
              WHERE Date_Occur >= DATEADD(yy,@pYear-1900,0)
                AND Date_Occur <  DATEADD(yy,@pYear-1900+1,0)
              GROUP BY DATEADD(mm,DATEDIFF(mm,0,Date_Occur),0)
            ) d
      ORDER BY d.MonthStart

    So far as the Order By being done somewhere else, you could not correctly sort the 3 character months externally without including an additional column in the output.  You'd always end up with "Apr" as the first month on a straight sort.  Or, you'd have to do some wierdo conversion back to the month ordinals (could be a built in function but why bother doing it there?) and then sort on those to get it right.  You've also made a bad assumption that original poster will be doing any external processing at all.  Frequently, especially with ETL, SQL IS the entire app... there is no middle tier to make things pretty in those cases.  No... getting the month order right on this problem should be one of the priorites of the SQL code especially since it's so very easy and efficient there.... it is just another simple form of data manipulation and that shouldn't be done in the middle tier.

    --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)

Viewing 11 posts - 1 through 10 (of 10 total)

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