Requête SQL à grouper par jour

135

Je veux lister toutes les ventes et regrouper la somme par jour.

Sales (saleID INT, amount INT, created DATETIME)

Mise à jour J'utilise SQL Server 2005

mrblah
la source
4
Vous devez spécifier la base de données que vous utilisez, car les fonctions de date sont différentes dans leurs dialectes SQL.
Guffa
Regardez ici pour plus d'informations sur le regroupement par jour. sqlserverlearner.com/2012/group-by-day-with-examples

Réponses:

164

si vous utilisez SQL Server,

dateadd(DAY,0, datediff(day,0, created)) retournera le jour créé

par exemple, si la vente a été créée le '2009-11-02 06: 12: 55.000', dateadd(DAY,0, datediff(day,0, created))renvoyez '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
la source
de votre tête, serait-il plus efficace de concevoir de cette façon ou d'utiliser simplement DATE et de grouper directement dessus?
Sinaesthetic le
@Sinaesthetic qui dépend des exigences.
Anwar Chandra
108

Pour SQL Server:

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

ou plus rapide (depuis Q8-Coder):

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

Pour MySQL:

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

ou mieux (de Jon Bright):

GROUP BY date(datefield)

Pour Oracle:

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

ou plus rapide (à partir d'IronGoofy):

GROUP BY trunc(created);

Pour Informix (par Jonathan Leffler):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
Andomar
la source
Merci d'avoir listé toutes les différentes syntaxes
CTS_AE
43

Si vous utilisez MySQL:

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

Si vous utilisez MS SQL 2008:

SELECT
    CAST(created AS date) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    CAST(created AS date)
Jon Bright
la source
5
J'ai peur que ces exemples
soient regroupés
Andomar, je viens d'essayer le MS SQL (après une petite modification de la syntaxe). Il regroupe heureusement par date ici. Je n'ai pas le temps d'essayer MySQL aussi, mais je l'utilise toute la journée dans mon travail quotidien et je suis plus ou moins certain qu'il sera également regroupé par date.
Jon Bright
@Jon Bright: Mon commentaire était avant une modification. L'actuel est toujours incorrect: le type de date n'est pris en charge que dans SQL Server 2008
Andomar
Andomar, puisque vous m'avez rendu incertain, je viens de vérifier celui de MySQL aussi. Cela fonctionne parfaitement et les groupes par date.
Jon Bright
Andomar, la modification n'a apporté aucune différence fonctionnelle au résultat, du moins en ce qui concerne le regroupement par date ou microsecondes. Si seulement 2008 prend en charge la date et l'heure (je n'ai pas regardé), cela ne rend pas la réponse incorrecte, cela ne s'applique qu'à MS SQL 2008. Il y a une différence.
Jon Bright
7

en fait, cela dépend du SGBD que vous utilisez, mais en SQL normal convert(varchar,DateColumn,101), le format DATETIME sera modifié à ce jour (un jour)

alors:

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

le nombre magix 101est le format de date dans lequel il est converti

yopefonic
la source
2
+1 Oui, ce que signifie 101 est expliqué ici msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar
7

Si vous utilisez SQL Server, vous pouvez ajouter trois champs calculés à votre 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

et maintenant vous pouvez facilement regrouper, classer par etc. par jour, mois ou année de la vente:

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

Ces champs calculés seront toujours tenus à jour (lorsque votre date "Créé" change), ils font partie de votre table, ils peuvent être utilisés comme des champs normaux, et peuvent même être indexés (s'ils sont "PERSISTÉS" ) - excellente fonctionnalité qui est totalement sous-utilisée, à mon humble avis.

Marc

marc_s
la source
Oui en effet! Très utile si vous avez besoin de rapporter un jour, un mois, une année tout le temps :-)
marc_s
2

Pour oracle, vous pouvez

group by trunc(created);

car cela tronque le datetime créé à minuit précédent.

Une autre option consiste à

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

qui permet d'obtenir le même résultat, mais peut être plus lent car il nécessite une conversion de type.

Thorsten
la source
C'est probablement assez spécifique à Oracle, mais assez pratique. Il y a aussi un tronc (..., 'MONTH') pour vous donner rapidement le premier jour du mois etc.
Thorsten
2

Pour PostgreSQL:

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

ou en utilisant cast:

GROUP BY timestampfield::date

si vous voulez de la vitesse, utilisez la deuxième option et ajoutez un index:

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

utiliser 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
la source