检查每个组的列中是否存在值

时间:2015-01-30 16:17:05

标签: sql postgresql

很难把我想做的事情放到单词中,所以搜索也很困难。

基本上我试图查看列中是否存在某个值,按组分区,然后向前传播该值。

在这个例子中,我想检查一个用户是否已经完成了教程并设置了一个结转的标志。

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

5 个答案:

答案 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; 这将为您提供一次完成本教程的所有用户。