根据时间范围对用户活动进行分组的 SQL 查询

Posted

技术标签:

【中文标题】根据时间范围对用户活动进行分组的 SQL 查询【英文标题】:SQL query to group user activity based on time range 【发布时间】:2017-06-05 04:25:05 【问题描述】:

我有一个包含两列的表,id 和 modifiedDate。我想查询此表以列出时间范围内每个 id 的活动。 我的桌子看起来像:

+-----+------------+
| ID  |     Date   |
+-----+------------+
| 1   | 2017.01.19 |
| 1   | 2017.01.18 |
| 1   | 2017.01.10 |
| 1   | 2017.01.09 |
| 2   | 2017.01.19 |
| 2   | 2017.01.18 |
| 2   | 2017.01.10 |
| 2   | 2017.01.09 |
+-----+------------+

Desired output: 

+-----+-----------------+------------+-------+
| ID  |     this week   | last week  | total |
+-----+-----------------+------------+-------+
| 1   |        2        |      2     |   4   | 
| 2   |        2        |      2     |   4   |
+-----+-----------------+------------+-------+

【问题讨论】:

您在这里使用的是 mysql 还是 Postgresql? (不要标记未涉及的产品。) 恢复上次编辑...这里的大多数人喜欢格式化文本,而不是图片。 请恢复为没有您的数据和所需结果的图片。如果您希望我们给您时间来帮助您,您至少可以花几分钟时间来格式化它。不发图的原因可以找here 在数据行和输出行的开头添加 4 个空格。这使得格式更好 您使用的是哪个 dbms?答案将取决于使用的产品! (标记 MySQL 或 Postgresql,或其他一些 dbms。) 【参考方案1】:

这就是 Oracle SQL 上的查询方式

 SELECT id, 
  COUNT(decode(to_char(t.modifydate,'iyyy-iw'),to_char(sysdate,'iyyy-iw'),1)) this_week, 
  COUNT(decode(to_char(t.modifydate,'iyyy-iw'),to_char(sysdate-7,'iyyy-iw'),1)) prev_week, 
  COUNT(id) total
FROM  test_tbl1 t
GROUP BY  id 

【讨论】:

【参考方案2】:

这应该在 MySQL 中工作

SELECT `id`, 
    COUNT(CASE WHEN WEEKOFYEAR(`date`) = WEEKOFYEAR(CURDATE()) THEN 1 END) this_week, 
    COUNT(CASE WHEN WEEKOFYEAR(`date`) = WEEKOFYEAR(CURDATE())-1 THEN 1 END) prev_week, 
    COUNT(id) total
FROM  `table`
GROUP BY `id`;

【讨论】:

这个用于TSQL SELECT id, COUNT(CASE WHEN DATEPART(wk,[Date]) = DATEPART(wk,GETDATE()) THEN 1 END) this_week, COUNT(CASE WHEN DATEPART(wk,[Date]) = DATEPART(wk,GETDATE())-1 THEN 1 END) prev_week, COUNT(id) total FROM yourtable GROUP BY id;【参考方案3】:

您需要条件聚合,可以使用 Postgres 中的 filter 子句很好地完成(自 9.4 起)

select id, 
       count(*) filter (where this_week), 
       count(*) filter (where last_week),
       count(*) as total
from (
  select id, 
         date_trunc('week', "date")::date = date_trunc('week', current_date)::date as this_week,
         date_trunc('week', "date")::date = date_trunc('week', current_date)::date - 7 as last_week
  from data
) t
group by id
order by id;

或者,您可以使用 to_char() 将日期缩短为周/年组合:

select id, 
       to_char("date", 'iyyy-iw') = to_char(current_date, 'iyyy-iw') as this_week,
       to_char("date", 'iyyy-iw') = to_char(current_date - 7, 'iyyy-iw') as last_week
from data

【讨论】:

以上是关于根据时间范围对用户活动进行分组的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

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

根据重叠时段对数据进行分组或求和

SQL根据开始和结束时间对满足条件的时间序列进行分组

Oracle SQL 查询对连续记录进行分组

SQL对查询结果进行分组

如何根据条件对sql中的行进行分组