102

I have a table with two fields - datetime and int. I want to do a group by on the datetime only on the date ignoring the hour and minute. The SELECT statement should return a date that maps to the sum of the int of a single day.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Steven
  • 1,143
  • 4
  • 10
  • 15

6 Answers6

168
SELECT CAST(Datetimefield AS DATE) as DateField, SUM(intfield) as SumField
FROM MyTable
GROUP BY CAST(Datetimefield AS DATE)
JNK
  • 63,321
  • 15
  • 122
  • 138
  • 11
    This will only work in SQL Server 2008+ (when the Date datatype was introduced). If you're in 2005 or earlier, changing the cast to convert(convert(int, Datetimefield), datetime) should work. – Derek Sep 14 '11 at 13:30
  • I'm getting an error saying that 'Type Date is not a defined system type'. – Steven Sep 14 '11 at 13:30
  • 5
    @Steven - then see Derek's comment. This is why it's a good idea to include your **VERSION** in the question. – JNK Sep 14 '11 at 13:31
  • @Derek this doesn't seem to work. A `select convert(convert(int, getdate()), datetime)` fails with wrong syntax error – rabudde Sep 14 '11 at 13:44
  • 1
    sorry, convert(datetime, convert(int, getdate())) – Derek Sep 14 '11 at 13:56
  • SQL Server 2022 has a potentially more efficient method https://stackoverflow.com/a/76761752/73226 – Martin Smith Jul 25 '23 at 10:24
25

As he didn't specify which version of SQL server he uses (date type isn't available in 2005), one could also use

SELECT CONVERT(VARCHAR(10),date_column,112),SUM(num_col) AS summed
FROM table_name
GROUP BY CONVERT(VARCHAR(10),date_column,112)
rabudde
  • 7,498
  • 6
  • 53
  • 91
  • In older versions like 2000/2005 varchar conversion for this need is slower than use of `DATEADD(dd, DATEDIFF(dd, 0, date_field),0)` – Paul Maxwell Oct 28 '17 at 21:46
9

I came researching the options that I would have to do this, however, I believe the method I use is the simplest:

SELECT COUNT(*), 
       DATEADD(dd, DATEDIFF(dd, 0, date_field),0) as dtgroup 
FROM TABLE 
GROUP BY DATEADD(dd, DATEDIFF(dd, 0, date_field),0) 
ORDER BY dtgroup ASC;
Carol
  • 1,852
  • 26
  • 29
Jefferson Silva
  • 235
  • 2
  • 8
  • 1
    This will work in any version of SQL Server and is faster than using varchar conversions. – Paul Maxwell Oct 28 '17 at 21:44
  • Could you clarify what is "dd"? I don't understand what you are supposed to put in it. – BelovedFool Oct 22 '18 at 13:24
  • "dd" is datepart equivalent to day. You can also use "day", "d" or "dd" – Jefferson Silva Nov 05 '18 at 14:34
  • For future readers: In case you adopt this good solution to rounding in seconds you will get an int overflow. That can be corrected by starting not from date "0", but a fixed date in the past that won't be accessed. Perhaps use the start of the year 2K. – Martin Jul 19 '23 at 14:09
3

-- I like this as the data type and the format remains consistent with a date time data type

;with cte as(
    select 
        cast(utcdate as date) UtcDay, DATEPART(hour, utcdate) UtcHour, count(*) as Counts
    from dbo.mytable cd 
    where utcdate between '2014-01-14' and '2014-01-15'
    group by
        cast(utcdate as date), DATEPART(hour, utcdate)
)
select dateadd(hour, utchour, cast(utcday as datetime)) as UTCDateHour, Counts
from cte
Jean-Bernard Pellerin
  • 12,556
  • 10
  • 57
  • 79
SqlHog
  • 31
  • 2
2

Personally i prefer the format function, allows you to simply change the date part very easily.

     declare @format varchar(100) = 'yyyy/MM/dd'
     select 
        format(the_date,@format), 
        sum(myfield) 
     from mytable 
     group by format(the_date,@format) 
     order by format(the_date,@format) desc;
Krik
  • 355
  • 4
  • 9
0

For SQL Server 2022+ you can use DATETRUNC.

This has an advantage over the other methods in that it is able to take advantage of the fact that an index ordered by datetime is also ordered by date and can avoid a sort operation.

e.g. Compare the below

CREATE TABLE #T(
Datetimefield DATETIME,
intfield INT,
)

CREATE INDEX IX ON #T(Datetimefield) INCLUDE (intfield)

SELECT CAST(Datetimefield AS DATE) AS DateField,
       SUM(intfield)               AS SumField
FROM   #T
GROUP  BY CAST(Datetimefield AS DATE) 

SELECT DATETRUNC(DAY,Datetimefield) AS DateField,
       SUM(intfield)               AS SumField
FROM   #T
GROUP  BY DATETRUNC(DAY,Datetimefield)

enter image description here

Martin Smith
  • 438,706
  • 87
  • 741
  • 845