按周分组,如何获得空周?

Posted

技术标签:

【中文标题】按周分组,如何获得空周?【英文标题】:Group by week, how to get empty weeks? 【发布时间】:2011-01-26 14:21:02 【问题描述】:

我有以下代码,它将一些事件 (YYYY-MM-DD HH:MM:SS) 分组为周,例如“Y:2010 - Week: 50”。

SELECT DATE_FORMAT(date, 'Y:%X - Week:%V') AS regweek, COUNT(*) as number 

效果很好,但我希望所有周都返回,即使没有放置事件的那些周也是如此。

如果第三周没有注册事件,此时我得到:

week 1: 10
week 2: 1
week 4: 2

我想得到:

week 1: 10
week 2: 1
week 3: 0
week 4: 2

【问题讨论】:

您想要从什么时候开始所有周?时间的开始? 从第一个事件发生或过去 N 个月开始的所有星期也可以。它应该只是一个“连续”的时间段 【参考方案1】:

SQL 不能返回某些表中不存在的行。为了获得您想要的效果,您将需要一个表 Weeks (WeekNo INT),其中一年中每个可能的周都有一行(IIRC 可能是 53 或 54 周,具体取决于您的计数方式)。

然后,使用 OUTER JOIN 将此表加入到您的常规结果中,以获得额外的周数。

SELECT DATE_FORMAT(date, 'Y:%X - Week:%V') AS regweek, COUNT(date) as number 
    FROM YourTable RIGHT OUTER JOIN Weeks ON WEEK(YourTable.date) = Weeks.WeekNo

[更新]:注意 COUNT(date) 而不是 COUNT(*) 的用户。将 COUNT 相加时,SQL 不会在日期列中包含 NULL 值。由于缺少的周中没有任何日期,因此这将正确地为您提供这些周的 0 个事件。

【讨论】:

感谢您的提示。我正在尝试按照这种方式进行操作,但是即使该周没有任何事件,正确的加入也会在特定的一周返回 number = 1,对吗? 您必须将 COUNT(*) 更改为 COUNT(date)。由于“缺失”周的日期将为 NULL,因此它不会包含在计数中。我会更新我的答案。 太棒了!如果我没记错的话,您的答案还需要“按 Weeks.WeekNo 分组”才能正常工作 是的,没错。我刚刚从原始问题中提取了您的 SQL 片段并添加了 JOIN,您仍然必须应用您之前使用的过滤、分组和排序(当然,使用 WeekNo 而不是 regweek)。【参考方案2】:

最后,我决定按以下方式解决问题,为几周创建一个临时表,并使用在上面的答案中找到的代码。

CREATE TEMPORARY TABLE weeks (
         id INT
       );
INSERT INTO weeks (id) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30), (31), (32), (33), (34), (35), (36), (37), (38), (39), (40), (41), (42), (43), (44), (45), (46), (47), (48), (49), (50), (51), (52), (53), (54);
SELECT 
w.id, COUNT(c.issuedate) as numberPerWeek
FROM tableName c RIGHT OUTER JOIN weeks w ON WEEK(c.issuedate) = w.id group by w.id;

【讨论】:

您实际上是在以这种方式创建一个临时数字表来产生结果 :-) 它们是一种很好的通用技术,值得一读。【参考方案3】:

这是制作数字/计数表的问题 - 只是一个从 0 计数到任何值的简单表。它们通常很有用,我总是建议将它们添加到您的数据库中。

有了这个,您可以相对轻松地动态生成周列表,而不需要特定的预先计算的周表(因此您不需要一个巨大的表或担心用完周),然后离开加入那个在您的约会列表中显示所有有约会的星期。

快速入门:

declare @min    datetime
set     @min    ='2010-01-01'

select
    dateadd(wk, number, @min) as weekDate
from
    numbers
where
    number between 0 and datediff(wk,@min,getdate())

【讨论】:

以上是关于按周分组,如何获得空周?的主要内容,如果未能解决你的问题,请参考以下文章

在熊猫中按周分组

SQL Server 按过去 24 小时、上周和上个月对促销进行分组,并按周降序排序

如何使用 Django ORM 按周分组

如何在打字稿/离子2中按周分组时间戳?

如何在 MySQL 中按周分组?

如何使用 EF Core 按周 对数据分组?