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


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))

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)

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)

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


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


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.


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));

-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)
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.