Group by not working as desired...

  • Hi all, 

    SELECT
      DATENAME (MONTH, [Date]) AS 'MONTH'
    -- , Replace([notes], 'Attended - ','' ) As 'Class Name'
     , --DATENAME(Day,[Date]) AS 'Day Of The Month',
      count(*) AS 'Attendance'
    FROM
     dbo.Logs
    Where
     [notes] like '%Attended%%' and Notes Like '%adult%'
     and Year([Date]) = '2017'
    GROUP BY
     [Date]
     --, Notes--,
     --datepart(Day,[Date])
    ORDER BY
     MONTH([Date])
     -- ,datepart(DD,[Date])
    ;

    Returns:

    MONTH Attendance
    January 12
    January 7
    January 10
    February 10
    February 9
    February 10
    etc...

    What I want is to group by month, so my result set only has 12 rows, however if I add a 'Distinct' clause, I get an error message, 
    "Order by items must appear in the select list if select distinct is specified"

    Schema/Sample: 


    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[logs](
     [id] [int] NOT NULL,
     [profileId] [int] NULL,
     [logId] [int] NULL,
     [date] [date] NOT NULL,
     [time] [datetime] NULL,
    )ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO
    Insert Into Logs
    Values
    ('244341', '1905', '3', '2011-06-09', '1899-12-30 19:31:54.000', 'Attended - Thursday Adult '),
    ('244342', '1905', '3', '2011-06-09', '1899-12-30 19:32:00.000', 'Thursday Intermediate/Advanced 7:30pm'),
    ('244343', '3678', '3', '2011-06-09' ,'1899-12-30 19:34:01.000', 'Attended - Thursday Intermediate/Advanced 7:30pm')
    Select top 10 *
    From Logs

    TIA

  • Yep, that's not gonna work, SQL needs the sort column in the data.  Here's one workaround:

    SELECT MONTH, Attendance
    FROM (
      SELECT
      DATENAME (MONTH, [Date]) AS 'MONTH',
      MAX(DATEPART (MONTH, [Date])) AS 'Month#',
      COUNT(*) AS 'Attendance'
      FROM
      dbo.Logs
      Where
      [notes] like '%Attended%%' and Notes Like '%adult%'
      and [Date] >= '20170101' and [Date] < '20180101'
      GROUP BY
      DATENAME (MONTH, [Date])
    ) AS derived
    ORDER BY
    Month#

    ;

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • JaybeeSQL - Tuesday, May 29, 2018 3:15 PM

    Hi all, 

    SELECT
      DATENAME (MONTH, [Date]) AS 'MONTH'
    -- , Replace([notes], 'Attended - ','' ) As 'Class Name'
     , --DATENAME(Day,[Date]) AS 'Day Of The Month',
      count(*) AS 'Attendance'
    FROM
     dbo.Logs
    Where
     [notes] like '%Attended%%' and Notes Like '%adult%'
     and Year([Date]) = '2017'
    GROUP BY
     [Date]
     --, Notes--,
     --datepart(Day,[Date])
    ORDER BY
     MONTH([Date])
     -- ,datepart(DD,[Date])
    ;

    Returns:

    MONTH Attendance
    January 12
    January 7
    January 10
    February 10
    February 9
    February 10
    etc...

    What I want is to group by month, so my result set only has 12 rows, however if I add a 'Distinct' clause, I get an error message, 
    "Order by items must appear in the select list if select distinct is specified"

    Schema/Sample: 

    CREATE TABLE [dbo].[logs](
    [id] [int] NOT NULL,
    [profileId] [int] NULL,
    [logId] [int] NULL,
    [date] [date] NOT NULL,
    [time] [datetime] NULL,
    [notes] [nvarchar](max) NULL
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    INSERT INTO #logs VALUES
        MONTH Attendance
    ('January' '12')
    ('January' '7')
    ('January' '10')
    ('February' '10')
    ('February' '9')
    ('February' '10
    ')
    SELECT * FROM #logs

    TIA

    Just curious, but have you tested the code you posted in an empty sandbox database?
    Nothing posted will help us with your question.

  • I suspect your problem is going to be in how your [DATE] field is stored.
    Would I be correct in presuming that field is stored as either a DATE or DATETIME?

  • JaybeeSQL - Tuesday, May 29, 2018 3:15 PM


    What I want is to group by month, so my result set only has 12 rows, however
     ...
    TIA

    If you want to group by MONTH, then why don't you in the query?

    Shouldn't
    GROUP BY
     [Date]

    be
    GROUP BY
     MONTH([Date])

    ** Don't mistake the ‘stupidity of the crowd’ for the ‘wisdom of the group’! **
  • HanShi - Wednesday, May 30, 2018 7:33 AM

    JaybeeSQL - Tuesday, May 29, 2018 3:15 PM


    What I want is to group by month, so my result set only has 12 rows, however
     ...
    TIA

    If you want to group by MONTH, then why don't you in the query?

    Shouldn't
    GROUP BY
     [Date]

    be
    GROUP BY
     MONTH([Date])

    What will you do when the span of the query passes through the end of a calendar year?   While you might not have to worry about getting unique values, you may have to worry about the order in which they appear.   More importantly, what do you do when the time span is longer than a year?   That will destroy your query's accuracy.

    Steve (aka sgmunson) 🙂 🙂 🙂
    Rent Servers for Income (picks and shovels strategy)

  • @steve-2: Agree, but the original query filters on one year. That makes my suggestion valid for this query. It may not be the case when different specs are required.

    ** Don't mistake the ‘stupidity of the crowd’ for the ‘wisdom of the group’! **
  • HanShi - Wednesday, May 30, 2018 12:39 PM

    @steve-2: Agree, but the original query filters on one year. That makes my suggestion valid for this query. It may not be the case when different specs are required.

    Yeah, I know...  My point was that future maintainability MAY be affected, and doing it right the first time avoids one heck of lot of work later, when the original has been repeatedly changed and enhanced over the course of a couple of years, and is then more important than it is now, and all of a sudden, business wants year over year, so two years worth of data are needed, and now you've got to redesign the whole shootin' match all because you "got lazy" up front...

    Steve (aka sgmunson) 🙂 🙂 🙂
    Rent Servers for Income (picks and shovels strategy)

  • ScottPletcher - Tuesday, May 29, 2018 3:26 PM

    Yep, that's not gonna work, SQL needs the sort column in the data.  Here's one workaround:

    SELECT MONTH, Attendance
    FROM (
      SELECT
      DATENAME (MONTH, [Date]) AS 'MONTH',
      MAX(DATEPART (MONTH, [Date])) AS 'Month#',
      COUNT(*) AS 'Attendance'
      FROM
      dbo.Logs
      Where
      [notes] like '%Attended%%' and Notes Like '%adult%'
      and [Date] >= '20170101' and [Date] < '20180101'
      GROUP BY
      DATENAME (MONTH, [Date])
    ) AS derived
    ORDER BY
    Month#

    ;

    That hit the spot -  pretty nifty workaround, using a subquery!!  I think that's what separates the DBA trying his hand at Dev , from the dedicated Dev. 

    Any idea how to change 'month' to days of the year, and display the actual date?  I tried 'Day', which only gets me 31 rows, in fact the correct number is 176 (as evinced by a select (distinct date)), using 'DayoftheYear' yields 176 rows, but displayed as integers from 1-365.  

     - Sample data/schema - heads up acknowledged, will correct for future posts.  
     - As above, the datatype for logs.date is Date.

  • Am I missing something, or would it be a lot easier as:

    select
     datename(month,[date]),
     count(*)
    from logs
    group by
     year([date]),
     datename(month,[date])
    order by
     year([date]),
     datename(month,[date])

    or just plain:

    select
     [date],
     count(*)
    from logs
    group by
     [date]
    order by
     [date]

    If you actually want a daily breakdown?

  • JaybeeSQL - Thursday, May 31, 2018 1:08 PM

    ScottPletcher - Tuesday, May 29, 2018 3:26 PM

    Yep, that's not gonna work, SQL needs the sort column in the data.  Here's one workaround:

    SELECT MONTH, Attendance
    FROM (
      SELECT
      DATENAME (MONTH, [Date]) AS 'MONTH',
      MAX(DATEPART (MONTH, [Date])) AS 'Month#',
      COUNT(*) AS 'Attendance'
      FROM
      dbo.Logs
      Where
      [notes] like '%Attended%%' and Notes Like '%adult%'
      and [Date] >= '20170101' and [Date] < '20180101'
      GROUP BY
      DATENAME (MONTH, [Date])
    ) AS derived
    ORDER BY
    Month#

    ;

    That hit the spot -  pretty nifty workaround, using a subquery!!  I think that's what separates the DBA trying his hand at Dev , from the dedicated Dev. 

    Any idea how to change 'month' to days of the year, and display the actual date?  I tried 'Day', which only gets me 31 rows, in fact the correct number is 176 (as evinced by a select (distinct date)), using 'DayoftheYear' yields 176 rows, but displayed as integers from 1-365.  

     - Sample data/schema - heads up acknowledged, will correct for future posts.  
     - As above, the datatype for logs.date is Date.

    LOL, I've been 100% full-time DBA since 1986.  I know SQL/T-SQLnot other development.


    SELECT
        DATEADD(DAY, DATEDIFF(DAY, 0, Date), Date) AS Day,
        COUNT(*) AS 'Attendance'
    FROM
        dbo.Logs
    WHERE
        [notes] like '%Attended%%' and Notes Like '%adult%'
        and [Date] >= '20170101' and [Date] < '20180101'
    GROUP BY
        DATEADD(DAY, DATEDIFF(DAY, 0, Date), Date)
    ORDER BY
        Day

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • ScottPletcher - Thursday, May 31, 2018 3:02 PM

    JaybeeSQL - Thursday, May 31, 2018 1:08 PM

    ScottPletcher - Tuesday, May 29, 2018 3:26 PM

    Yep, that's not gonna work, SQL needs the sort column in the data.  Here's one workaround:

    SELECT MONTH, Attendance
    FROM (
      SELECT
      DATENAME (MONTH, [Date]) AS 'MONTH',
      MAX(DATEPART (MONTH, [Date])) AS 'Month#',
      COUNT(*) AS 'Attendance'
      FROM
      dbo.Logs
      Where
      [notes] like '%Attended%%' and Notes Like '%adult%'
      and [Date] >= '20170101' and [Date] < '20180101'
      GROUP BY
      DATENAME (MONTH, [Date])
    ) AS derived
    ORDER BY
    Month#

    ;

    That hit the spot -  pretty nifty workaround, using a subquery!!  I think that's what separates the DBA trying his hand at Dev , from the dedicated Dev. 

    Any idea how to change 'month' to days of the year, and display the actual date?  I tried 'Day', which only gets me 31 rows, in fact the correct number is 176 (as evinced by a select (distinct date)), using 'DayoftheYear' yields 176 rows, but displayed as integers from 1-365.  

     - Sample data/schema - heads up acknowledged, will correct for future posts.  
     - As above, the datatype for logs.date is Date.

    LOL, I've been 100% full-time DBA since 1986.  I know SQL/T-SQLnot other development.


    SELECT
        DATEADD(DAY, DATEDIFF(DAY, 0, Date), Date) AS Day,
        COUNT(*) AS 'Attendance'
    FROM
        dbo.Logs
    WHERE
        [notes] like '%Attended%%' and Notes Like '%adult%'
        and [Date] >= '20170101' and [Date] < '20180101'
    GROUP BY
        DATEADD(DAY, DATEDIFF(DAY, 0, Date), Date)
    ORDER BY
        Day

    That nearly does the trick, however the result yields
    2134-01-04 6
    2134-01-06 13
    2134-01-08 9
    2134-01-10 16
    2134-01-18 8

    Not sure where the '2134/5' comes from.  Though both rowcounts are the same, Andy's 'Day' reply yields
    2017-01-02 6
    2017-01-03 13
    2017-01-04 9
    2017-01-05 16
    2017-01-09 8

    1986????!! !!!  Sweeeeet Jesus.  That explains everything.  I was barely old enough to slobber over the lead singer of The Bangles in '86...

    Btw , I noticed I seem to be learning a lot from you lately.  Thanks for that 🙂

  • JaybeeSQL - Thursday, May 31, 2018 5:36 PM

    Not sure where the '2134/5' comes from.  Though both rowcounts are the same, Andy's 'Day' reply yields

    I suspect he was aiming for DATEADD(DAY, DATEDIFF(DAY, 0, [Date]), 0) and missed. 😉 It's an old school trick from the pre-SQL 2008 days that is equivalent to Cast([Date] As Date) in that it strips the time portion off a DateTime type. You don't actually need it at all in your case since your [Date] column is actually a Date type already and so won't have a Time portion to worry about, which is why it looks right in my results.

    And trying to write that sentence alone is a good reason to never name your columns [Date]! (Or any other SQL reserved word)

Viewing 13 posts - 1 through 12 (of 12 total)

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