Consulta SQL para agrupar por día


134

Quiero enumerar todas las ventas y agrupar la suma por día.

Sales (saleID INT, amount INT, created DATETIME)

Actualización Estoy usando SQL Server 2005


44
Debe especificar qué base de datos está utilizando, ya que las funciones de fecha son diferentes en sus dialectos SQL.
Guffa el

Mire aquí para obtener más información sobre la agrupación por día. sqlserverlearner.com/2012/group-by-day-with-examples

Respuestas:


164

si estás usando SQL Server,

dateadd(DAY,0, datediff(day,0, created)) devolverá el día creado

por ejemplo, si la venta se creó el '2009-11-02 06: 12: 55.000', dateadd(DAY,0, datediff(day,0, created))devuelva '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))

fuera de la cabeza, ¿sería más eficiente diseñar de esta manera o simplemente usar DATE y agruparlo directamente?
Sinaesthetic

@Sinestésico que depende de los requisitos.
Anwar Chandra

108

Para SQL Server:

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

o más rápido (desde Q8-Coder):

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

Para MySQL:

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

o mejor (de Jon Bright):

GROUP BY date(datefield)

Para Oracle:

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

o más rápido (de IronGoofy):

GROUP BY trunc(created);

Para Informix (por Jonathan Leffler):

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

Gracias por enumerar todas las sintaxis diferentes
CTS_AE

43

Si estás usando MySQL:

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

Si está utilizando MS SQL 2008:

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

55
Me temo que estos ejemplos se
agruparán

Andomar, acabo de probar el MS SQL (después de un pequeño ajuste a la sintaxis). Felizmente agrupa por fecha aquí. No tengo tiempo para ir a probar MySQL también, pero lo uso todo el día en mi trabajo diario y estoy más o menos seguro de que también se agrupará por fecha.
Jon Bright el

@ Jon Bright: Mi comentario fue antes de una edición. El actual sigue siendo incorrecto: el tipo de fecha solo es compatible con SQL Server 2008
Andomar el

Andomar, ya que me hizo sentir inseguro, acabo de revisar el MySQL también. Funciona perfectamente y se agrupa por fecha.
Jon Bright el

Andomar, la edición hizo cero diferencia funcional para el resultado, al menos en lo que respecta a la agrupación por fecha o microsegundos. Si solo 2008 admite la fecha y hora (no lo he buscado), eso no hace que la respuesta sea incorrecta, solo se aplica a MS SQL 2008. Hay una diferencia.
Jon Bright el

7

en realidad esto depende de qué DBMS esté usando, pero en SQL regular convert(varchar,DateColumn,101)cambiará el formato DATETIME a la fecha (un día)

entonces:

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

el número magix 101es a qué formato de fecha se convierte


2
+1 Sí, lo que significa 101 se explica aquí msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar el

7

Si está utilizando SQL Server, puede agregar tres campos calculados a su tabla:

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

y ahora puede agrupar fácilmente, ordenar por etc. por día, mes o año de la venta:

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

Esos campos calculados siempre se mantendrán actualizados (cuando cambie la fecha "Creado"), son parte de su tabla, se pueden usar como los campos normales e incluso se pueden indexar (si están "PERSISTADOS" ) - gran característica que está totalmente subutilizada, en mi humilde opinión.

Bagazo


Si de hecho! Bastante útil si tiene que ser informar sobre el día, mes, año todo el tiempo :-)
marc_s

2

Por oráculo puedes

group by trunc(created);

ya que esto trunca la fecha y hora creada a la medianoche anterior.

Otra opción es

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

que logra el mismo resultado, pero puede ser más lento ya que requiere una conversión de tipo.


Eso es probablemente bastante específico de Oracle, pero bastante útil. También hay un trunc (..., 'MES') para darle rápidamente el primer día del mes, etc.
Thorsten

2

Para PostgreSQL:

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

o usando el elenco:

GROUP BY timestampfield::date

si quieres velocidad, usa la segunda opción y agrega un índice:

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

-3

usar 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)
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.