mysql - 使用 GROUP BY 获取合适的日期

标签 mysql sql

我有一个表格,用于跟踪用户每天观看电影的时长。 现在我想计算基于日期的唯一观看次数。

所以条件是:

  • 每个用户的最大观看次数为 1
  • View = 1 如果一个用户的 SUM(duration) >= 120
  • 一旦 SUM(duration) 达到 120,就应该确定日期

但这里的问题是获取正确的日期行。例如 row1.duration + row2.duration >= 120 因此 view count = 1 应该应用于 2021-10-16

| id | user_id | duration | created_at | film_id |
+----+---------+----------+------------+---------+
| 1  | 1       | 80       | 2021-10-15 | 1       |
| 2  | 1       | 70       | 2021-10-16 | 1       |
| 3  | 1       | 200      | 2021-10-17 | 2       |
| 4  | 2       | 50       | 2021-10-18 | 1       |
| 5  | 2       | 90       | 2021-10-18 | 1       |
| 6  | 3       | 140      | 2021-10-18 | 2       |
| 7  | 4       | 10       | 2021-10-19 | 3       |

预期结果:

| cnt   | created_at |
+-------+------------+
| 0     | 2021-10-15 |
| 1     | 2021-10-16 |
| 0     | 2021-10-17 |
| 2     | 2021-10-18 |
| 0     | 2021-10-19 |

这是我尝试过的方法,但它选择了第一次约会,并忽略了 0 次。 这是 fiddle填充数据

SELECT count(*) AS cnt,
         created_at
FROM 
    (SELECT user_id,
         sum(duration) AS total,
         created_at
    FROM watch_time
    GROUP BY  user_id) AS t
WHERE t.total >= 120
GROUP BY  created_at;

是否有机会通过 SQL 完成这项工作,或者应该在应用程序级别完成?

提前致谢!

更新:

版本:AWS RDS MySQL 5.7.33

但如果有帮助,我可以切换到 Postgres。

非常感谢即使有一种方法可以获得 MIN(date) 但包含所有日期(包括 0 次观看)。

比这个好。

SELECT IFNULL(cnt, 0) as cnt,
         t3.created_at
FROM 
    (SELECT count(*) AS cnt,
         created_at
    FROM 
        (SELECT user_id,
         sum(duration) AS total,
         created_at
        FROM watch_time
        GROUP BY  user_id) AS t
        WHERE t.total >= 120
        GROUP BY  created_at) AS t2
    RIGHT JOIN 
    (SELECT distinct(created_at)
    FROM watch_time) AS t3
    ON t2.created_at = t3.created_at;

返回:

| cnt   | created_at |
+-------+------------+
| 1     | 2021-10-15 |
| 0     | 2021-10-16 |
| 0     | 2021-10-17 |
| 2     | 2021-10-18 |
| 0     | 2021-10-19 |

但我不确定日期 (2021-10-15) 是随机取的还是总是最低的日期

更新 2:

是否也可以包含 film_id?就像将 user_id、film_id 视为唯一 View 而不是仅按 user_id 分组。

所以在这种情况下:

row1 & row2 都有user_id: 1film_id: 1,结果是1 view ,因为它们的 durations 之和 >= 120。因此本例中的日期将为 2021-10-16

但是 row3user_id: 1film_id: 2,并且 duration >= 120 它也是日期为 2021-10-17

的 1 个 View
| id | user_id | duration | created_at | film_id |
+----+---------+----------+------------+---------+
| 1  | 1       | 80       | 2021-10-15 | 1       |
| 2  | 1       | 70       | 2021-10-16 | 1       |
| 3  | 1       | 200      | 2021-10-17 | 2       |
| 4  | 2       | 50       | 2021-10-18 | 1       |
| 5  | 2       | 90       | 2021-10-18 | 1       |
| 6  | 3       | 140      | 2021-10-18 | 2       |
| 7  | 4       | 10       | 2021-10-19 | 3       |

预期结果:

| cnt   | created_at |
+-------+------------+
| 0     | 2021-10-15 |
| 1     | 2021-10-16 |
| 1     | 2021-10-17 |
| 2     | 2021-10-18 |
| 0     | 2021-10-19 |

最佳答案

使用 MySQL 变量,它可以实现你的计数逻辑,它基本上按 user_id 和 created_at 对表行进行排序,并逐行计算

http://sqlfiddle.com/#!9/569088/14

SELECT created_at, SUM(CASE WHEN duration >= 120 THEN 1 ELSE 0 END) counts
FROM (
  SELECT user_id, created_at, 
  CASE WHEN @UID != user_id THEN @SUM_TIME := 0 WHEN @SUM_TIME >= 120 AND @DT != created_at THEN @SUM_TIME := 0 - duration ELSE 0 END SX,
  @SUM_TIME := @SUM_TIME + duration AS duration,
  @UID := user_id,
  @DT := created_at
  FROM watch_time
  JOIN ( SELECT @SUM_TIME :=0, @DT := NOW(), @UID := '' ) t
  ORDER BY user_id, created_at
) f
GROUP BY created_at

关于mysql - 使用 GROUP BY 获取合适的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69637217/

相关文章:

php - 给定用户的位置,选择在其半径范围内包含该用户的行

mysql - 更改 makefile 后 C makefile 无法编译

mysql - 使用数组删除Mysql记录

mysql - 使用变量选择列

sql - 如何获取 mysql 字段的 max_length

php - 如何在 PHP 中访问未知名称的复选框

php - Laravel Auth::user 在其他 Controller 中找不到

mysql - 3 个表的内部联接如何获取日期最大值的 Id?

c# - 将WITH ROLLUP SQL 语句转换为LINQ

mysql - SQL自动从另一个表插入ID