Consulta SQL para Agrupar por dia

134

Quero listar todas as vendas e agrupar a soma por dia.

Sales (saleID INT, amount INT, created DATETIME)

Atualização Estou usando o SQL Server 2005

mrblah
fonte
4
Você precisa especificar qual banco de dados está usando, pois as funções de data são diferentes em seus dialetos SQL.
Guffa
Veja aqui mais informações sobre o agrupamento por dia. sqlserverlearner.com/2012/group-by-day-with-examples

Respostas:

164

se você estiver usando o SQL Server,

dateadd(DAY,0, datediff(day,0, created)) retornará o dia criado

por exemplo, se a venda criada em '2009-11-02 06: 12: 55.000', dateadd(DAY,0, datediff(day,0, created))retorne '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
fonte
de cabeça para baixo, seria mais eficiente projetar dessa maneira ou simplesmente usar DATE e agrupá-la diretamente?
Sinaesthetic
@ Sinestésico que depende dos requisitos.
Anwar Chandra
108

Para o SQL Server:

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

ou mais rápido (do Q8-Coder):

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

Para o MySQL:

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

ou melhor (de Jon Bright):

GROUP BY date(datefield)

Para Oracle:

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

ou mais rápido (da IronGoofy):

GROUP BY trunc(created);

Para Informix (de Jonathan Leffler):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
Andomar
fonte
Obrigado por listar todas as diferentes sintaxes
CTS_AE 29/10
43

Se você estiver usando o MySQL:

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

Se você estiver usando o MS SQL 2008:

SELECT
    CAST(created AS date) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    CAST(created AS date)
Jon Bright
fonte
5
Temo Estes exemplos grupo por microssegundo
Andomar
Andomar, eu apenas tentei o MS SQL (após um pequeno ajuste na sintaxe). Felizmente agrupa por data aqui. Não tenho tempo para experimentar o MySQL também, mas uso o dia todo no meu trabalho diário e tenho mais ou menos certeza de que ele também será agrupado por data.
Jon Brilhante
@ Jon Bright: Meu comentário foi antes de uma edição. O atual ainda está incorreto: o tipo de data só é suportada no SQL Server 2008
Andomar
Andomar, desde que você me deixou insegura, acabei de fazer uma verificação no MySQL também. Funciona perfeitamente e agrupa por data.
Jon Brilhante
Além disso, a edição não fez diferença funcional no resultado, pelo menos no que diz respeito ao agrupamento por data ou microssegundos. Se apenas 2008 suporta a data e hora (eu não olhei), isso não torna a resposta incorreta, ela só se aplica ao MS SQL 2008. Há uma diferença.
911 Jon Bright
7

na verdade, isso depende do DBMS que você está usando, mas no SQL regular convert(varchar,DateColumn,101) , o formato DATETIME será alterado para data (um dia)

tão:

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

o número magix 101é para qual formato de data é convertido

yopefonic
fonte
2
+1 sim ele faz, o que 101 meios é explicado aqui msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar
7

Se você estiver usando o SQL Server, poderá adicionar três campos calculados à sua tabela:

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 agora você pode facilmente agrupar, ordenar por etc. por dia, mês ou ano da venda:

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

Esses campos calculados serão sempre atualizados (quando a data "Criada" for alterada), eles fazem parte da sua tabela, podem ser usados ​​como campos regulares e podem até ser indexados (se estiverem "PERSISTED" ) - ótimo recurso totalmente subutilizado, IMHO.

Marc

marc_s
fonte
Sim, de fato! Muito útil se você precisa ser informando sobre o dia, mês, ano o tempo todo :-)
marc_s
2

Para oracle você pode

group by trunc(created);

pois isso trunca o datetime criado para a meia-noite anterior.

Outra opção é

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

que alcança o mesmo resultado, mas pode ser mais lento, pois requer uma conversão de tipo.

Thorsten
fonte
Provavelmente isso é bastante específico da Oracle, mas bastante útil. Há também um trunc (..., 'MONTH') para dar-lhe rapidamente o primeiro dia do mês etc.
Thorsten
2

Para o PostgreSQL:

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

ou usando elenco:

GROUP BY timestampfield::date

se você deseja velocidade, use a segunda opção e adicione um índice:

CREATE INDEX tablename_timestampfield_date_idx ON  tablename(date(timestampfield));
Francisco Valdez
fonte
-3

use 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)
}
liubinqiang
fonte