Sql запрос в группу по дням

135

Я хочу перечислить все продажи и сгруппировать сумму по дням.

Sales (saleID INT, amount INT, created DATETIME)

Обновление, я использую SQL Server 2005

mrblah
источник
4
Вы должны указать, какую базу данных вы используете, поскольку функции даты различаются по своим диалектам SQL.
Guffa
Подробнее о группировке по дням читайте здесь. sqlserverlearner.com/2012/group-by-day-with-examples

Ответы:

164

если вы используете SQL Server,

dateadd(DAY,0, datediff(day,0, created)) вернет день создания

например, если сделка создана «2009-11-02 06: 12: 55.000», dateadd(DAY,0, datediff(day,0, created))верните «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))
Анвар Чандра
источник
вне головы, что было бы эффективнее спроектировать таким образом или просто использовать DATE и сгруппировать его напрямую?
Sinaesthetic
@Sinaestetic, который зависит от требований.
Анвар Чандра
108

Для SQL Server:

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

или быстрее (от Q8-Coder):

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

Для MySQL:

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

или лучше (от Джона Брайта):

GROUP BY date(datefield)

Для Oracle:

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

или быстрее (от IronGoofy):

GROUP BY trunc(created);

Для Informix (от Джонатана Леффлера):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
Andomar
источник
Спасибо за перечисление различных синтаксисов
CTS_AE
43

Если вы используете MySQL:

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

Если вы используете MS SQL 2008:

SELECT
    CAST(created AS date) AS saledate,
    SUM(amount)
FROM
    Sales
GROUP BY
    CAST(created AS date)
Джон Брайт
источник
5
Боюсь, что эти примеры сгруппируются по микросекундам
Andomar 01
Andomar, я только что попробовал MS SQL (после незначительной настройки синтаксиса). Здесь он сгруппирован по дате. У меня тоже нет времени пойти и попробовать MySQL, но я использую его весь день в своей повседневной работе и более или менее уверен, что он также будет сгруппирован по дате.
Джон Брайт
@Jon Bright: Мой комментарий был до редактирования. Текущее значение все еще неверно: тип даты поддерживается только в SQL Server 2008
Andomar,
Андомар, раз уж вы меня неуверенно сказали, я только что проверил и MySQL. Работает отлично и группируется по дате.
Джон Брайт
Andomar, изменение не повлияло на результат, по крайней мере, в том, что касается группировки по дате или микросекундам. Если только 2008 поддерживает дату и время (я не смотрел), это не делает ответ неверным, это применимо только к MS SQL 2008. Есть разница.
Джон Брайт
7

на самом деле это зависит от того, какую СУБД вы используете, но в обычном SQL convert(varchar,DateColumn,101)изменит формат DATETIME на дату (один день)

так:

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

число magix 101- это формат даты, в который он конвертируется

yopefonic
источник
2
+1 Да, есть, что означает 101, объяснено здесь msdn.microsoft.com/en-us/library/ms187928.aspx
Andomar 01
7

Если вы используете SQL Server, вы можете добавить три вычисляемых поля в таблицу:

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

и теперь вы можете легко группировать, упорядочивать и т. д. по дню, месяцу или году продажи:

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

Эти вычисляемые поля всегда будут обновляться (при изменении даты "Создано"), они являются частью вашей таблицы, их можно использовать так же, как обычные поля, и даже их можно индексировать (если они "ПРОДОЛЖАЮТСЯ" ) - отличная функция, которая полностью не используется, ИМХО.

Марк

marc_s
источник
Да, в самом деле! Очень полезно, если вам нужно постоянно отчитываться за день, месяц, год :-)
marc_s
2

Для оракула вы можете

group by trunc(created);

поскольку это усекает созданное datetime до предыдущей полуночи.

Другой вариант заключается в

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

который дает тот же результат, но может быть медленнее, поскольку требует преобразования типа.

Торстен
источник
Это, вероятно, довольно специфично для Oracle, но весьма удобно. Также есть усечение (..., 'МЕСЯЦ'), чтобы быстро указать первый день месяца и т. Д.
Торстен,
2

Для PostgreSQL:

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

или используя cast:

GROUP BY timestampfield::date

если вам нужна скорость, используйте второй вариант и добавьте индекс:

CREATE INDEX tablename_timestampfield_date_idx ON  tablename(date(timestampfield));
Франсиско Вальдес
источник
-3

использовать 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
источник