SQL-Abfrage an Gruppe nach Tag gruppieren

134

Ich möchte alle Verkäufe auflisten und die Summe nach Tag gruppieren.

Sales (saleID INT, amount INT, created DATETIME)

Update Ich verwende SQL Server 2005

mrblah
quelle
4
Sie müssen angeben, welche Datenbank Sie verwenden, da sich die Datumsfunktionen in ihren SQL-Dialekten unterscheiden.
Guffa
Weitere Informationen zur Gruppierung nach Tag finden Sie hier. sqlserverlearner.com/2012/group-by-day-with-examples

Antworten:

164

Wenn Sie SQL Server verwenden,

dateadd(DAY,0, datediff(day,0, created)) gibt den erstellten Tag zurück

Wenn der Verkauf beispielsweise am '2009-11-02 06: 12: 55.000' erstellt wurde, dateadd(DAY,0, datediff(day,0, created))geben Sie '2009-11-02 00: 00: 00.000' zurück.

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
quelle
Wäre es effizienter, auf diese Weise zu entwerfen oder einfach DATE zu verwenden und direkt darauf zu gruppieren?
Sinaesthetic
@Sinaesthetic, das von den Anforderungen abhängt.
Anwar Chandra
108

Für SQL Server:

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

oder schneller (vom Q8-Coder):

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

Für MySQL:

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

oder besser (von Jon Bright):

GROUP BY date(datefield)

Für Oracle:

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

oder schneller (von IronGoofy):

GROUP BY trunc(created);

Für Informix (von Jonathan Leffler):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
Andomar
quelle
Vielen Dank für die Auflistung der verschiedenen Syntaxen
CTS_AE
43

Wenn Sie MySQL verwenden:

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

Wenn Sie MS SQL 2008 verwenden:

SELECT
    CAST(created AS date) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    CAST(created AS date)
Jon Bright
quelle
5
Ich fürchte, diese Beispiele werden nach Mikrosekunden
gruppiert
Andomar, ich habe gerade MS SQL ausprobiert (nach einer kleinen Änderung der Syntax). Hier gruppiert es sich gerne nach Datum. Ich habe keine Zeit, MySQL auszuprobieren, aber ich benutze es den ganzen Tag in meinem Tagesjob und bin mehr oder weniger sicher, dass es auch nach Datum gruppiert wird.
Jon Bright
@ Jon Bright: Mein Kommentar war vor einer Bearbeitung. Der aktuelle ist immer noch falsch: Der
Datumstyp
Andomar, da du mich unsicher gemacht hast, habe ich gerade auch MySQL überprüft. Es funktioniert perfekt und gruppiert sich nach Datum.
Jon Bright
Andomar, die Bearbeitung machte keinen funktionalen Unterschied zum Ergebnis, zumindest was die Gruppierung nach Datum oder Mikrosekunden betrifft. Wenn nur 2008 das Datum und die Uhrzeit unterstützt (ich habe nicht nachgesehen), wird die Antwort dadurch nicht falsch, sondern nur für MS SQL 2008. Es gibt einen Unterschied.
Jon Bright
7

convert(varchar,DateColumn,101)Tatsächlich hängt dies davon ab, welches DBMS Sie verwenden. In regulärem SQL wird das DATETIME-Format jedoch auf das Datum (einen Tag) geändert.

so:

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

die magix nummer 101 gibt an, in welches Datumsformat sie konvertiert wird

yopefonic
quelle
2
+1 Ja, was 101 bedeutet, wird hier erklärt. Msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar
7

Wenn Sie SQL Server verwenden, können Sie Ihrer Tabelle drei berechnete Felder hinzufügen:

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

und jetzt können Sie leicht nach Tag, Monat oder Jahr des Verkaufs gruppieren, bestellen usw.:

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

Diese berechneten Felder werden immer auf dem neuesten Stand gehalten (wenn sich Ihr "Erstellungsdatum" ändert), sie sind Teil Ihrer Tabelle, sie können wie normale Felder verwendet und sogar indiziert werden (wenn sie "PERSISTED" sind). ) - tolles Feature, das meiner Meinung nach völlig ungenutzt ist.

Marc

marc_s
quelle
Ja in der Tat! Sehr nützlich, wenn Sie
ständig
2

Für Orakel kannst du

group by trunc(created);

da dies die erstellte Datumszeit auf die vorherige Mitternacht abschneidet.

Eine andere Option ist zu

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

Dies erzielt das gleiche Ergebnis, kann jedoch langsamer sein, da eine Typkonvertierung erforderlich ist.

Thorsten
quelle
Das ist wahrscheinlich ziemlich Oracle-spezifisch, aber ziemlich praktisch. Es gibt auch eine Kürzung (..., 'MONAT'), um Ihnen schnell den ersten Tag des Monats usw. zu geben.
Thorsten
2

Für PostgreSQL:

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

oder mit Besetzung:

GROUP BY timestampfield::date

Wenn Sie Geschwindigkeit wünschen, verwenden Sie die zweite Option und fügen Sie einen Index hinzu:

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

benutze 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
quelle