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.


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

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)

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)

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


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


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.


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

-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)
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.