Zapytanie SQL do grupowania według dnia

137

Chcę wymienić wszystkie sprzedaże i pogrupować sumę według dni.

Sales (saleID INT, amount INT, created DATETIME)

UWAGA: używam programu SQL Server 2005.

mrblah
źródło
4
Musisz określić, jakiej bazy danych używasz, ponieważ funkcje daty różnią się w ich dialektach SQL.
Guffa
Zajrzyj tutaj, aby uzyskać więcej informacji na temat grupowania według dnia. sqlserverlearner.com/2012/group-by-day-with-examples

Odpowiedzi:

168

jeśli używasz SQL Server,

dateadd(DAY,0, datediff(day,0, created)) zwróci utworzony dzień

na przykład, jeśli sprzedaż utworzona dnia „2009-11-02 06: 12: 55.000”, dateadd(DAY,0, datediff(day,0, created))zwraca „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
źródło
od góry do głowy, czy bardziej efektywne byłoby zaprojektowanie w ten sposób, czy po prostu użycie DATY i grupowanie na niej bezpośrednio?
Sinaesthetic,
@Sinaesthetic, który zależy od wymagań.
Anwar Chandra
114

W przypadku programu SQL Server:

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

lub szybszy (z Q8-Coder):

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

W przypadku MySQL:

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

lub lepiej (od Jona Brighta):

GROUP BY date(datefield)

W przypadku Oracle:

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

lub szybciej (z IronGoofy):

GROUP BY trunc(created);

Informix (autor: Jonathan Leffler):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
Andomar
źródło
Dziękujemy za
wypisanie
50

Jeśli używasz MySQL:

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

Jeśli używasz MS SQL 2008:

SELECT
    CAST(created AS date) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    CAST(created AS date)
Jon Bright
źródło
6
Obawiam się, że te przykłady zostaną pogrupowane według mikrosekundy
Andomar
Andomar, właśnie wypróbowałem MS SQL (po drobnych poprawkach w składni). Tutaj szczęśliwie grupuje się według dat. Nie mam czasu, żeby iść i wypróbować MySQL, ale używam go przez cały dzień w mojej codziennej pracy i jestem mniej więcej pewien, że będzie on również grupowany według daty.
Jon Bright
@Jon Bright: Mój komentarz był przed edycją. Bieżący jest nadal niepoprawny: typ daty jest obsługiwany tylko w programie SQL Server 2008
Andomar
Andomar, ponieważ wzbudziłeś wątpliwości, właśnie odwiedziłem i sprawdziłem również MySQL. Działa doskonale i grupuje według daty.
Jon Bright
Andomar, edycja nie spowodowała żadnej różnicy funkcjonalnej w wyniku, przynajmniej jeśli chodzi o grupowanie według daty lub mikrosekund. Jeśli tylko 2008 obsługuje datę i godzinę (nie szukałem), to nie oznacza, że ​​odpowiedź jest nieprawidłowa, oznacza to, że dotyczy tylko MS SQL 2008. Jest różnica.
Jon Bright
7

faktycznie zależy to od używanego DBMS, ale w zwykłym SQL convert(varchar,DateColumn,101)zmieni aktualny format DATETIME (jeden dzień)

więc:

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

liczba magix 101to format daty, na który jest konwertowana

yopefonic
źródło
2
+1 Tak, to znaczy 101 wyjaśniono tutaj msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar
7

Jeśli używasz SQL Server, możesz dodać do swojej tabeli trzy pola obliczeniowe:

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

a teraz możesz łatwo grupować, zamawiać itp. według dnia, miesiąca lub roku sprzedaży:

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

Te pola obliczeniowe będą zawsze aktualne (gdy zmieni się data utworzenia), są częścią tabeli, można ich używać tak jak zwykłych pól, a nawet indeksować (jeśli są „UTRWALONE” ) - świetna funkcja, która jest całkowicie niedostatecznie wykorzystywana, IMHO.

Marc

marc_s
źródło
W rzeczy samej! Całkiem przydatne, jeśli musisz cały czas raportować dzień, miesiąc, rok :-)
marc_s
2

Dla wyroczni możesz

group by trunc(created);

ponieważ powoduje to obcięcie utworzonej daty i godziny do poprzedniej północy.

Inną opcją jest

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

który daje ten sam wynik, ale może być wolniejszy, ponieważ wymaga konwersji typu.

Thorsten
źródło
To prawdopodobnie dość specyficzne dla Oracle, ale całkiem przydatne. Jest też skrót (..., 'MIESIĄC'), aby szybko podać pierwszy dzień miesiąca itp.
Thorsten
2

W przypadku PostgreSQL:

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

lub używając obsady:

GROUP BY timestampfield::date

jeśli chcesz szybkości, użyj drugiej opcji i dodaj indeks:

CREATE INDEX tablename_timestampfield_date_idx ON  tablename(date(timestampfield));
Francisco Valdez
źródło
-3

użyj 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
źródło