CASE 将忽略重复条目

CASE will ignore duplicate entries

我有一个存储用户投票的 table,像这样:

+----+---------+-------+---------+
| id | post_id | value | user_id |
+----+---------+-------+---------+
| 1  |   103   |   1   |    1    |
| 2  |   105   |   1   |    3    |
| 3  |   106   |   1   |    1    |
| 4  |   108   |   0   |    1    |
| 5  |   108   |   0   |    2    |
| 6  |   105   |   0   |    2    |
| 7  |   105   |   1   |    1    |
+----+---------+-------+---------+

其中 id 是投票 ID,post_id 是 Post ID,value 是 like/unlike 的布尔值(1 = 喜欢,0 = 不喜欢) 并且 user_id 是选民 ID。

我想要一个列表,其中包含:

  1. 全部post
  2. 每个post的赞数
  3. 每个 post 的不同计数
  4. 用户(例如,用户 1)投票的投票 ID。所以我可以稍后更新值
  5. 用户投票

所以我写了这个查询:

SELECT
    post_id, 
    COUNT(
        CASE 
            WHEN value = 1 
            THEN 1 
        END
    ) AS likes, 
    COUNT(
        CASE 
            WHEN value = 0 
            THEN 1 
        END
    ) AS unlikes, 
    (CASE 
        WHEN user_id = 1    -- I choose user_id manually
        THEN id 
    END) AS vote_id, 
    (CASE 
        WHEN user_id = 1 
        THEN value 
    END) AS user_vote 
FROM votes 
GROUP BY post_id;

我期望的是这样的:

+---------+-------+---------+---------+-----------+
| post_id | likes | unlikes | vote_id | user_vote |
+---------+-------+---------+---------+-----------+
|   103   |   1   |    0    |    1    |     1     |
|   105   |   2   |    1    |    7    |     1     |
|   106   |   1   |    0    |    3    |     1     |
|   108   |   0   |    2    |    4    |     0     |
+---------+-------+---------+---------+-----------+

但这是我得到的结果:

+---------+-------+---------+---------+-----------+
| post_id | likes | unlikes | vote_id | user_vote |
+---------+-------+---------+---------+-----------+
|   103   |   1   |    0    |   1     |    1      |
|   105   |   2   |    1    |   NULL  |    NULL   |
|   106   |   1   |    0    |   3     |    1      |
|   108   |   0   |    2    |   4     |    0      |
+---------+-------+---------+---------+-----------+

那些 NULL 值是由于我查询的最后一行 (GROUP BY post_id) 而产生的。如果 table 中有重复的 post_id(例如,如果其他用户已经为 post 投票),CASE 将忽略它并且 return NULL.

我该怎么办?

您的查询的问题是最后两列缺少聚合。假设用户只能为 post 投票一次,您可以安全地使用 MAX()(或 MIN())组合值,因为最多有一个匹配行:

SELECT v.post_id, SUM(value = 1) AS likes, SUM(value = 0) AS unlikes,
       MAX(CASE WHEN user_id = 1 THEN vote_id END) AS user1_voteid,
       MAX(CASE WHEN user_id = 1 THEN value END) AS user1_vote
FROM votes v
GROUP BY v.post_id;