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。
我想要一个列表,其中包含:
- 全部post
- 每个post的赞数
- 每个 post 的不同计数
- 用户(例如,用户 1)投票的投票 ID。所以我可以稍后更新值
- 用户投票
所以我写了这个查询:
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;
我有一个存储用户投票的 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。
我想要一个列表,其中包含:
- 全部post
- 每个post的赞数
- 每个 post 的不同计数
- 用户(例如,用户 1)投票的投票 ID。所以我可以稍后更新值
- 用户投票
所以我写了这个查询:
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;