很难把我想做的事情放到单词中,所以搜索也很困难。
基本上我试图查看列中是否存在某个值,按组分区,然后向前传播该值。
在这个例子中,我想检查一个用户是否已经完成了教程并设置了一个结转的标志。
pk | user | ... | activity
1 | A | ... | "login"
2 | A | ... | "started_tutorial"
3 | A | ... | "completed_tutorial"
4 | A | ... | "some other activity"
5 | A | ... | "logout"
5 | B | ... | "login"
6 | B | ... | "logout"
我认为这应该是
select *,
check(activity in ('completed_tutorial')) as completed_activity
from tbl
但我不认为我可以在select语句中使用check
,这将是一个常量标志,而不是在找到它之后才设置为true。
我想要得到的例子:
pk | user | ... | activity | completed_tutorial
1 | A | ... | "login" | 0
2 | A | ... | "started_tutorial" | 0
3 | A | ... | "completed_tutorial" | 1
4 | A | ... | "some other activity" | 1
5 | A | ... | "logout" | 1
5 | B | ... | "login" | 0
6 | B | ... | "logout" | 0
答案 0 :(得分:3)
您可以使用HAVING
clause过滤SQL组。例如,您可以按用户及其活动对表进行分组,然后对其进行过滤以仅包含已完成教程的那些:
SELECT user FROM tbl
GROUP BY user, activity
HAVING activity = 'completed_tutorial';
编辑: OP编辑完问题后,这是我的新答案。在这里,我假设你的表有一个日期字段。
SELECT *, COALESCE(date >= (
SELECT date FROM tbl WHERE activity = 'completed_tutorial'
AND user = outertbl.user
), FALSE)
FROM tbl AS outertbl
ORDER BY date
请注意,这种查询在未经优化时基本上是N²,因此我建议您只是从数据库中获取数据,然后在程序中处理它。
答案 1 :(得分:1)
你可以尝试这样的事情
SELECT a.*, coalesce(b.completed, 0)
FROM tbl a
LEFT JOIN (SELECT user, 1 completed
FROM tbl
WHERE user = a.user
AND activity='completed_tutorial') b
ON a.user = b.user AND b.pk >= a.pk
它假定最多有一行activity='completed_tutorial'
,并且该用户标识“会话”。如果用户可以制作多个教程,则必须添加另一个字段。
答案 2 :(得分:1)
我不确定这个的速度,但是下面的解决方案呢?
SELECT
user
,max(CASE
WHEN activity = "completed_tutorial" THEN 1
ELSE 0
END) AS completed_tutorial
FROM tbl
GROUP BY user
;
答案 3 :(得分:0)
SELECT user FROM tbl
GROUP BY user
HAVING COUNT(CASE WHEN activity = 'completed_tutorial' THEN 1 ELSE 0 END) = 1;
这将为您提供至少完成一次教程的所有用户。
答案 4 :(得分:0)
从tbl选择用户 按用户分组 HAVING COUNT(活动='completed_tutorial'THEN 1 ELSE 0 END的情况下)= 1; 这将为您提供一次完成本教程的所有用户。