views:

399

answers:

6

I want to list all sales, and group the sum by day.

Sales (saleID INT, amount INT, created DATETIME)

Update I am using SQL Server 2005

+5  A: 

if you're using SQL Server,

dateadd(DAY,0, datediff(day,0, created) will return the day created

for example, if the sale created on '2009-11-02 06:12:55.000', dateadd(DAY,0, datediff(day,0, created) return '2009-11-02 00:00:00.000'

select sum(amount) as total, dateadd(DAY,0, datediff(day,0, created)) as created
from sales
group by dateadd(DAY,0, datediff(day,0, created))
Anwar Chandra
+1 Nice, SQL Server specific I'd guess
Andomar
+1  A: 

If you're using MySQL:

SELECT
    DATE(created) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    saledate

If you're using MS SQL 2008:

SELECT
    CAST(created AS date) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    CAST(created AS date) AS saledate
Jon Bright
I'm afraid these examples will group by microsecond
Andomar
Andomar, I just tried the MS SQL one (after a minor tweak to the syntax). It happily groups by date here. I don't have time to go and try MySQL too, but I use it all day in my day job and I'm more or less certain that it's going to group by date too.
Jon Bright
@Jon Bright: My comment was before an edit. The current one is still incorrect: the date type is only supported in SQL Server 2008
Andomar
Andomar, since you made me unsure, I've just been and checked the MySQL one too. It works perfectly and groups by date.
Jon Bright
@Jon Bright: Well cheers (I didn't downvote or antyhing)
Andomar
Andomar, the edit made zero functional difference to the result, at least as concerns grouping by date or microseconds. If only 2008 supports the date time (I haven't looked), that doesn't make the answer incorrect, it makes it only apply to MS SQL 2008. There's a difference.
Jon Bright
it has too group by DAY.
mrblah
+1 @Jon Bright: Well I'll upvote this one then, since you didn't ;)
Andomar
Andomar, thanks. I've updated the answer to reflect the 2k8 requirement. Now leaving well alone, since it turns out with the update to the question that neither of my answers are relevant :-)
Jon Bright
+1  A: 

For oracle you can

group by trunc(created);

as this truncates the created datetime to the previous midnight.

Another option is to

group by to_char(created, 'DD.MM.YYYY');

which achieves the same result, but may be slower as it requires a type conversion.

IronGoofy
+1 Interesting trunc() !
Andomar
That's probably quite Oracle-specific, but quite handy. There is also a trunc(..., 'MONTH') to quickly give you the first day of the month etc.
IronGoofy
+2  A: 

For SQL Server:

GROUP BY datepart(year,datefield), 
    datepart(month,datefield), 
    datepart(day,datefield)

or faster (from Q8-Coder):

GROUP BY dateadd(DAY,0, datediff(day,0, created))

For MySQL:

GROUP BY year(datefield), month(datefield), day(datefield)

or better (from Jon Bright):

GROUP BY date(datefield)

For Oracle:

GROUP BY to_char(datefield, 'yyyy-mm-dd')

or faster (from IronGoofy):

GROUP BY trunc(created);

For Informix (by Jonathan Leffler):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
Andomar
+2  A: 

actually this depends on what DBMS you are using but in regular SQL convert(varchar,DateColumn,101) will change the DATETIME format to date (one day)

so:

SELECT 
    sum(amount) 
FROM 
    sales 
GROUP BY 
    convert(varchar,created,101)

the magix number 101 is what date format it is converted to

yopefonic
+1 Yeah it does, what 101 means is explained here http://msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar
+2  A: 

If you're using SQL Server, you could add three calculated fields to your table:

Sales (saleID INT, amount INT, created DATETIME)

ALTER TABLE dbo.Sales
  ADD SaleYear AS YEAR(Created) PERSISTED
ALTER TABLE dbo.Sales
  ADD SaleMonth AS MONTH(Created) PERSISTED
ALTER TABLE dbo.Sales
  ADD SaleDay AS DAY(Created) PERSISTED

and now you could easily group by, order by etc. by day, month or year of the sale:

SELECT SaleDay, SUM(Amount)
FROM dbo.Sales
GROUP BY SaleDay

Those calculated fields will always be kept up to date (when your "Created" date changes), they're part of your table, they can be used just like regular fields, and can even be indexed (if they're "PERSISTED") - great feature that's totally underused, IMHO.

Marc

marc_s
+1 This would allow you to create an index on a datepart :)
Andomar
Yes indeed! Quite useful if you need to be reporting on day, month, year all the time :-)
marc_s
what about DAY(Created) ?
mrblah
@mrblah: sure, you can do that - over and over and over again.....
marc_s