SQL 按日期分组,但也获取不带记录的日期

Posted

技术标签:

【中文标题】SQL 按日期分组,但也获取不带记录的日期【英文标题】:SQL group by date, but get dates w/o records too 【发布时间】:2010-09-28 21:11:19 【问题描述】:

是否有一种简单的方法来创建一个包含一段时间内所有日期的GROUP BY DATE(timestamp),无论是否有任何与该日期相关的记录?

基本上,我需要生成这样的报告:

24 Dec - 0 orders
23 Dec - 10 orders
22 Dec - 8 orders
21 Dec - 2 orders
20 Dec - 0 orders

【问题讨论】:

认为没有明显的方法可以做到这一点,但我想我会问。感谢所有回复的人。 【参考方案1】:

一种方法是创建一个日历表并加入它。

我会永久创建它,然后创建一个插入新日期的任务,它可以每周、每天、每月等完成。

请注意,我假设您将时间戳转换为日期。

【讨论】:

虽然比创建动态生成列表的 SP 性能更高,但维护起来有点麻烦。 这里的维护问题确实意味着创建日历表是不合适的。您最终会得到一个作为整个数据库中心的日历表,并且调试变得非常困难。 @Neil,我必须说我同意,但我不喜欢动态创建日历表,除非它当然是定期而不是经常进行。跨度> 【参考方案2】:

不要使用 GROUP BY,而是创建一个包含您想要的特定日期的表(可能是临时表),例如:

24 Dec
23 Dec
22 Dec
21 Dec
20 Dec

然后,将该表连接到 Orders 表。

【讨论】:

虽然是一种有效的方法,但 Thangalin 下面的回答以编程方式执行此操作,而无需创建任何新表。 Thangallin 说,“在 Oracle 中”,但 OP 将问题标记为“mysql”。【参考方案3】:

您需要生成一个中间结果集,其中包含您希望包含在输出中的所有日期...

如果您在存储过程中执行此操作,那么您可以创建一个临时表或表变量(我不知道 MySQL 的功能),但是一旦您将所有日期都放在表或某种结果集中

使用外连接从临时表中加入真实数据a

在 SQL Server 中是这样的

  Declare @Dates Table (aDate DateTime Not Null)
  Declare @StartDt DateTime Set @StartDt = 'Dec 1 2008'
  Declare @EndDt   DateTime Set @EndDt   = 'Dec 31 2008'
  While @StartDt < @EndDt Begin
    Insert @Dates(aDate) Values(@StartDt)
    Set @StartDt = DateAdd(Day, 1, @StartDt)
  End

   Select D.aDate, Count(O.*) Orders
   From @Dates D Left Join 
      OrderTable O On O.OrderDate = D.aDate
   Group By D.aDate

【讨论】:

【参考方案4】:

在数据仓库中,采用的方法是创建一个包含所有日期的表,并在您的数据和日期表之间创建一个外键。我并不是说这对你来说是最好的方法,只是说它是在需要以多种方式汇总大量数据以进行报告的情况下的最佳做法。

如果您在 SQL Server 上使用报告层,您只需编写一些逻辑,在数据返回之后和呈现报告之前插入感兴趣的范围内缺少的日期。

如果您直接从 SQL Server 创建报表,并且您还没有数据仓库,并且现在没有时间或需要创建一个,我会创建一个日期表并加入它。进行连接并获得所需输出所需的格式可能有点不稳定,但它会完成工作。

【讨论】:

【参考方案5】:

假设您的订单比日期多,这样的事情可能会奏效:

select date, count(id) as orders
from
(
  SELECT DATE_ADD('2008-01-01', INTERVAL @rn:=@rn+1 DAY) as date from (select @rn:=-1)t, `order` limit 365
) d left outer join `order` using (date)
group by date

【讨论】:

我知道必须有一种方法可以在没有日历或数字表的情况下做到这一点。这很容易适应其他间隔(我需要每 15 分钟分组一次)。【参考方案6】:

有一种非常简单的方法可以做到这一点……只是我不记得了。但我从this thread 改编了这个查询:

SELECT 
    DISTINCT(LEFT(date_field,11)) AS `Date`,
    COUNT(LEFT(date_field,11)) AS `Number of events`
FROM events_table
GROUP BY `Date`

它也适用于 MySQL

【讨论】:

这行不通,因为它会省略任何没有事件的日期。 啊,真的。我想这个答案只有在您愿意以编程方式填写空白时才能考虑

以上是关于SQL 按日期分组,但也获取不带记录的日期的主要内容,如果未能解决你的问题,请参考以下文章

Eloquent 获取按日期分组的最后一条记录

按最新日期获取分组后的列

SQL 查询根据日期获取最新的 3 次发送,然后对记录进行分组

SQL:按日期分组并对列中的值求和

使用按日期分组的 sql 查询

mysql |按时间分组计数记录