Postgresql - 选择'投票'计数但仅包括最新的

时间:2012-12-11 19:21:48

标签: postgresql

我一直盯着它看了20分钟,无法绕过它。我以前做过,我只是不记得在哪个项目中(所以我可以参考代码)。

我有一张桌子:

votes [table]
  id - serial , primary
  useraccount_id - id
  object_id - id
  vote - int
  timestamp_vote - timestamp

我需要能够为任何一个对象选择当前的总票数。

然而 - 此表也充当“时间轴”视图。请注意,我使用序列作为id列。 useraccount_id + object_id

可能有多个记录

不幸的是,这不是我需要的:

SELECT 
   vote , count(vote)
FROM 
   votes
WHERE
   object_id = 161 
GROUP BY 
   vote ;

我知道需要使用子查询和distinct,以及'按时间戳desc排序',以限制给定用户的最新投票。我只是不记得如何将SELECT串在一起。

- 添加样本数据 -

样本数据

 id | object_id  | useraccount_id |     timestamp_created      | vote 
----+------------+----------------+----------------------------+------------
  2 |        153 |             57 | 2012-12-11 18:37:20.421013 |    1
  3 |        153 |             57 | 2012-12-11 18:48:39.963748 |    2
  4 |        153 |             57 | 2012-12-11 18:48:42.869945 |    3
  5 |        153 |             57 | 2012-12-11 18:48:48.991617 |    1
  6 |        153 |             57 | 2012-12-11 19:34:26.701351 |    2
  7 |        153 |             57 | 2012-12-11 19:35:52.449031 |    3
  8 |        153 |             57 | 2012-12-11 19:35:52.986822 |    1
  9 |        153 |             57 | 2012-12-11 19:35:53.850291 |    2
 10 |        153 |             58 | 2012-12-11 19:35:55.884202 |    3
 12 |        153 |             58 | 2012-12-11 19:35:56.803337 |    1
 13 |        153 |             59 | 2012-12-11 19:37:04.563519 |    3
 15 |        153 |             60 | 2012-12-11 19:37:40.618324 |    3
 16 |        153 |             61 | 2012-12-11 19:37:40.618324 |    3
 17 |        153 |             62 | 2012-12-11 19:37:40.618324 |    3
 18 |        153 |             63 | 2012-12-11 19:37:40.618324 |    2

预期输出为:

vote | count
-----+------
1    | 1        # user 58 cast a vote of `3` , then `1`.  only the latest vote of `1` counted.
2    | 2        # user 57 switched votes many times. only their last vote of `2` counted. user 63 cast a vote of `2` as well.
3    | 4        # users 59,60,61,62 all voted `3`

2 个答案:

答案 0 :(得分:2)

select vote, 
       count(vote) as cnt
from (
   select vote, 
          row_number() over (partition by vote order by timestamp_created desc) as rn
   from votes
)
where rn = 1
group by vote;

答案 1 :(得分:1)

你可以尝试这样的事情:

SELECT DISTINCT ON (useraccount_id, object_id) 
       vote, 
       timestamp_vote,
       useraccount_id,
       object_id
FROM votes
WHERE object_id = 161 -- your filter here
ORDER BY useraccount_id, object_id, timestamp_vote DESC

它将为您提供每个(useraccount_id, object_id)的最后一次投票。

然后:

SELECT SUM (CASE WHEN vote THEN 1 ELSE 0 END) as true_vote_sum,
       SUM (CASE WHEN vote THEN 0 ELSE 1 END) as false_vote_sum
FROM (SELECT DISTINCT ON (useraccount_id, object_id) 
             vote
      FROM votes
      WHERE object_id = 161 -- your filter here
      ORDER BY useraccount_id, object_id, timestamp_vote DESC)

获得投票数。

详细信息:DISTINCT ONCASE WHEN