Query SQL da raggruppare per giorno


134

Voglio elencare tutte le vendite e raggruppare la somma per giorno.

Sales (saleID INT, amount INT, created DATETIME)

Aggiornamento Sto usando SQL Server 2005


4
Devi specificare quale database stai usando, poiché le funzioni di data sono diverse nei loro dialetti SQL.
Guffa,

Guarda qui per maggiori informazioni sul raggruppamento per giorno. sqlserverlearner.com/2012/group-by-day-with-examples

Risposte:


164

se stai usando SQL Server,

dateadd(DAY,0, datediff(day,0, created)) restituirà il giorno creato

ad esempio, se la vendita creata in data "2009-11-02 06: 12: 55.000", dateadd(DAY,0, datediff(day,0, created))restituire "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))

dalla parte superiore della tua testa, sarebbe più efficace progettare in questo modo o semplicemente usare DATE e raggrupparti direttamente su di esso?
Sinaesthetic,

@Sinaestetico che dipende dai requisiti.
Anwar Chandra,

108

Per SQL Server:

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

o più veloce (da Q8-Coder):

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

Per MySQL:

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

o meglio (da Jon Bright):

GROUP BY date(datefield)

Per Oracle:

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

o più veloce (da IronGoofy):

GROUP BY trunc(created);

Per Informix (di Jonathan Leffler):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)

Grazie per aver elencato tutte le diverse sintassi
CTS_AE

43

Se stai usando MySQL:

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

Se stai usando MS SQL 2008:

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

5
Temo che questi esempi verranno raggruppati per microsecondo
Andomar,

Andomar, ho appena provato quello MS SQL (dopo una piccola modifica alla sintassi). Raggruppa felicemente per data qui. Non ho tempo di andare a provare anche MySQL, ma lo uso tutto il giorno nel mio lavoro quotidiano e sono più o meno certo che raggrupperà anche per data.
Jon Bright,

@Jon Bright: il mio commento era prima di una modifica. Quello attuale è ancora errato: il tipo di data è supportato solo in SQL Server 2008
Andomar

Andomar, dal momento che mi hai reso insicuro, sono appena stato e ho controllato anche quello di MySQL. Funziona perfettamente e raggruppa per data.
Jon Bright,

Andomar, la modifica ha fatto la differenza funzionale zero per il risultato, almeno per quanto riguarda il raggruppamento per data o microsecondi. Se solo il 2008 supporta l'ora della data (non ho guardato), ciò non rende la risposta errata, ma si applica solo a MS SQL 2008. C'è una differenza.
Jon Bright,

7

in realtà questo dipende da quale DBMS stai usando, ma in SQL normale convert(varchar,DateColumn,101)cambierà il formato DATETIME fino ad oggi (un giorno)

così:

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

il numero magix 101è il formato di data in cui viene convertito


2
1 Sì lo fa, ciò significa 101 è spiegato qui msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar

7

Se si utilizza SQL Server, è possibile aggiungere tre campi calcolati alla tabella:

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

e ora puoi facilmente raggruppare, ordinare per ecc. per giorno, mese o anno di vendita:

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

Quei campi calcolati saranno sempre aggiornati (quando la tua data "Creata" cambia), fanno parte della tua tabella, possono essere usati proprio come i campi normali e possono anche essere indicizzati (se sono "PERSISTATI" ) - grande funzionalità totalmente sottoutilizzata, IMHO.

Marc


Si Certamente! Abbastanza utile se devi riferire in continuazione giorno, mese, anno :-)
marc_s

2

Per oracolo puoi

group by trunc(created);

poiché ciò tronca il datetime creato alla mezzanotte precedente.

Un'altra opzione è quella di

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

che ottiene lo stesso risultato, ma può essere più lento in quanto richiede una conversione del tipo.


Questo è probabilmente abbastanza specifico per Oracle, ma abbastanza utile. C'è anche un tronco (..., 'MESE') per darti rapidamente il primo giorno del mese ecc.
Thorsten,

2

Per PostgreSQL:

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

o usando il cast:

GROUP BY timestampfield::date

se vuoi la velocità, usa la seconda opzione e aggiungi un indice:

CREATE INDEX tablename_timestampfield_date_idx ON  tablename(date(timestampfield));

-3

usa linq

from c in Customers
group c by DbFunctions.TruncateTime(c.CreateTime) into date
orderby date.Key descending
select new  
{
    Value = date.Count().ToString(),
    Name = date.Key.ToString().Substring(0, 10)
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.