0

我有以下数据:

id  vote_id  user_id  status 
1   1        1        1         the vote is active 
2   1        1        2         vote is canceled 
3   1        1        1         vote is active again 

status 一开始总是为 1,然后如果 status 为 2,则投票被取消。在第三行,用户再次行动,其状态为活动。仅当之后没有取消行时,我才需要能够选择一行

考虑到我不仅需要为每个用户 1 个 vote_id 执行此操作,我如何才能获取所有仍处于活动状态的用户的所有行!?

完整的数据样本将如下所示:

id  vote_id  user_id  status 
1   1        1        1         - vote1 is active 
2   1        1        2         - vote1 is canceled 
3   1        1        1         - vote1 is active again 
4   2        1        1         - vote2 is active 
5   2        1        2         - vote2 is canceled 

我只需要第 3 行,因为 (1-2) 和 (4-5) 相互抵消。

4

2 回答 2

1

鉴于情况

id, vote_id, user_id, status 
1,1,1,1 - the vote is active 
2,1,1,2 - vote is canceled 
3,1,1,1 - vote is active again 

我假设系统不允许取消投票,除非该投票处于活动状态,也不允许重新激活,除非它处于取消状态。

因此,如果“状态 1”的投票数量等于“状态 2”的数量,则该投票被取消;否则它是活动的。

在这个假设下,

SELECT id, vote_id, user_id, active AS status FROM
    ( SELECT MAX(id) AS id,
           SUM(CASE WHEN status = 1 THEN 1 WHEN status = 2 THEN -1 ELSE 0 END)
              AS active,
           user_id,
           vote_id
    FROM votes GROUP BY user_id, vote_id ) AS votes
WHERE votes.status = 1;

或者——我不喜欢这个,因为status名字不明确——

SELECT MAX(id) AS id,
    SUM(CASE WHEN status = 1 THEN 1 WHEN status = 2 THEN -1 ELSE 0 END) AS status,
    user_id,
    vote_id
FROM votes GROUP BY user_id, vote_id
HAVING status = 1;

如果您确定状态值,并且没有其他值,您也可以尝试

SUM((1-status)*2+1) AS status

但我不知道速度增益(如果有的话!)是否可以弥补清晰度的不足。

于 2012-09-25T21:05:42.833 回答
0

我想出了这个

select t.*
from @temp t
left join (select max(id) as lastCanceledId, vote_id
            from @temp
            where status = 2
            group by vote_id) cancels on t.vote_id = cancels.vote_id
where COALESCE(cancels.lastCanceledId, 0) < t.id
and t.Status = 1

其中@temp 是您的表的名称。中间的选择找到给定 vote_id 的最后取消的行。外部过滤掉取消行之前的所有行。这假设 id 表示事情发生的顺序。

于 2012-09-25T21:10:15.690 回答