如何用SQL统计仅上周参与活动本周未参与的用户
问题描述
需要按滚动周度统计用户是否参与活动,但仅将上周参与过活动的用户标记为“未参与”。例如,若用户参与第1周和第7周活动,仅在第2周和第8周将其计为“未参与”。
数据示例
events表(所有周度活动日期及递增唯一Event_ID)
| Event_Date | Event_ID |
|---|---|
| 2023-03-09 | 1 |
| 2023-03-16 | 2 |
| 2023-03-23 | 3 |
users表(用户参与的活动记录)
| Event_Date | Event_ID | User_ID |
|---|---|---|
| 2023-03-09 | 1 | 151 |
| 2023-03-16 | 2 | 151 |
| 2023-03-23 | 3 | 151 |
| 2023-03-09 | 1 | 299 |
| 2023-03-23 | 3 | 299 |
| 2023-03-16 | 2 | 373 |
期望输出
仅统计上周参与过活动但本周未参与的记录:
| Missed_Event_Date | Missed_Event_ID | User_ID |
|---|---|---|
| 2023-03-16 | 2 | 299 |
| 2023-03-23 | 3 | 373 |
尝试的错误SQL
SELECT Event_ID + 1, User_ID FROM users u WHERE NOT EXISTS (SELECT 1 FROM events WHERE u.Event_ID=e.Event_ID + 1)
正确SQL实现方案
核心思路:先定位用户参与过的所有活动,关联出该活动的下一周活动,再筛选出用户未参与下一周活动的记录,最终关联events表获取缺失活动的日期信息。
方案一:LEFT JOIN筛选法
SELECT e_next.Event_Date AS Missed_Event_Date, e_next.Event_ID AS Missed_Event_ID, u.User_ID FROM users u -- 关联用户参与的当前活动 JOIN events e_current ON u.Event_ID = e_current.Event_ID -- 关联当前活动的下一周活动(利用Event_ID递增特性) JOIN events e_next ON e_current.Event_ID + 1 = e_next.Event_ID -- 左连接用户参与记录,判断是否参与下一周活动 LEFT JOIN users u_miss ON u_miss.User_ID = u.User_ID AND u_miss.Event_ID = e_next.Event_ID -- 筛选未参与的记录 WHERE u_miss.User_ID IS NULL -- 去重,避免同一用户因重复参与上周活动导致输出重复 GROUP BY e_next.Event_Date, e_next.Event_ID, u.User_ID;
方案二:NOT EXISTS子查询法
SELECT e_next.Event_Date AS Missed_Event_Date, e_next.Event_ID AS Missed_Event_ID, u.User_ID FROM users u JOIN events e_current ON u.Event_ID = e_current.Event_ID JOIN events e_next ON e_current.Event_ID + 1 = e_next.Event_ID -- 子查询判断用户是否未参与下一周活动 WHERE NOT EXISTS ( SELECT 1 FROM users u_check WHERE u_check.User_ID = u.User_ID AND u_check.Event_ID = e_next.Event_ID ) GROUP BY e_next.Event_Date, e_next.Event_ID, u.User_ID;
逻辑说明
- 通过
users与events的关联,明确用户参与的当前活动; - 利用
Event_ID递增的特性,关联出当前活动的下一周活动; - 用
LEFT JOIN或NOT EXISTS判断用户是否参与了下一周活动,未参与的即为目标记录; - 加入
GROUP BY是为了避免同一用户因多次参与同一上周活动(如同一Event_ID有多条记录)导致重复输出。
内容的提问来源于stack exchange,提问作者Scarlett
相关产品推荐
相关产品推荐

