按天分组的 SQL 查询

Posted

技术标签:

【中文标题】按天分组的 SQL 查询【英文标题】:SQL query to group by day 【发布时间】:2010-12-12 02:45:42 【问题描述】:

我想列出所有销售额,并按天对总和进行分组。

Sales (saleID INT, amount INT, created DATETIME)

注意:我使用的是 SQL Server 2005。

【问题讨论】:

你必须指定你使用的数据库,因为日期函数在它们的 SQL 方言中是不同的。 查看此处了解有关按天分组的更多信息。 sqlserverlearner.com/2012/group-by-day-with-examples 【参考方案1】:

如果您使用的是 SQL Server,

dateadd(DAY,0, datediff(day,0, created)) 将返回创建日期

例如,如果销售创建于“2009-11-02 06:12:55.000”, dateadd(DAY,0, datediff(day,0, created)) return '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 取决于要求。【参考方案2】:

如果您使用的是 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)

【讨论】:

恐怕这些例子会按微秒分组 Andomar,我刚刚尝试了 MS SQL(在对语法稍作调整之后)。它在这里愉快地按日期分组。我也没有时间去尝试 MySQL,但我在日常工作中整天都在使用它,而且我或多或少地确定它也会按日期分组。 @Jon Bright:我的评论是在编辑之前。现在的还是不正确:日期类型只支持SQL Server 2008 Andomar,既然你让我不确定,我也刚刚检查过 MySQL 的。它可以完美运行并按日期分组。 Andomar,编辑对结果的功能差异为零,至少在按日期或微秒分组方面。如果只有 2008 支持日期时间(我没看过),那不会使答案不正确,它只适用于 MS SQL 2008。有区别。【参考方案3】:

对于甲骨文你可以

group by trunc(created);

因为这会将创建的日期时间截断到前一个午夜。

另一个选择是

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

实现相同的结果,但可能会更慢,因为它需要类型转换。

【讨论】:

这可能是特定于 Oracle 的,但非常方便。还有一个 trunc(..., 'MONTH') 可以快速给你当月的第一天等。【参考方案4】:

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

或更好(来自 Jon Bright):

GROUP BY date(datefield)

对于甲骨文:

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

或更快(来自 IronGoofy):

GROUP BY trunc(created);

对于 Informix(由 Jonathan Leffler 撰写):

GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)

【讨论】:

感谢您列出所有不同的语法【参考方案5】:

实际上这取决于您使用的 DBMS,但在常规 SQL 中 convert(varchar,DateColumn,101) 会将 DATETIME 格式更改为日期(一天)

所以:

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

magix 数字101 是它转换成的日期格式

【讨论】:

+1 确实如此,这里解释了 101 的含义msdn.microsoft.com/en-us/library/ms187928.aspx【参考方案6】:

如果您使用的是 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

这些计算字段将始终保持最新(当您的“创建”日期更改时),它们是您表格的一部分,它们可以像常规字段一样使用,甚至可以被索引(如果它们是"PERSISTED") - 伟大的功能完全没有被充分利用,恕我直言。

马克

【讨论】:

【参考方案7】:

对于 PostgreSQL:

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

或使用演员表:

GROUP BY timestampfield::date

如果你想要速度,使用第二个选项并添加一个索引:

CREATE INDEX tablename_timestampfield_date_idx ON  tablename(date(timestampfield));

【讨论】:

【参考方案8】:

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

【讨论】:

以上是关于按天分组的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQL Server 在此查询中按天对结果进行分组?

SQL Count 按天分组

MySQL实现按天分组统计,提供完整日期列表,无数据自动补0

使用 Laravel 查询数据并按天分组

PostgreSQL 查询按天计数/分组并显示没有数据的天数

Grafana 图表按天或月分组?