我可以减少这个查询吗?

问题描述

我有一个表名 likes,用于存储有关帖子的喜欢和不喜欢的详细信息。要显示帖子的总点赞数,我需要计算喜欢和不喜欢之间的差异。现在我将喜欢存储在名为 liked 的列中,该列的类型为 bool。这个想法是,如果喜欢,则将其设置为真,不喜欢为假。我的桌子看起来像这样,

| id | user_id | post_id | liked | 
| -- | ------- | ------- | ----- |
| 1  | 1       | 1       | true  |
| 2  | 7       | 1       | false |
| 3  | 12      | 1       | true  |

我使用了 SELECT liked,COUNT(*) FROM likes WHERE post_id=1 GROUP BY liked;,它返回了

| liked | count |
| ----- | ----- |
| TRUE  | 2     |
| FALSE | 1     |

我想看看这两者之间的区别。似乎找不到任何东西,所以我尝试了
SELECT SUM((SELECT COUNT(*) FROM likes WHERE post_id=1 AND liked = true) - (SELECT COUNT(*) FROM likes WHERE post_id=1 AND liked = false));

返回我想要的

| SUM |
| --- |
| 1   |

但我仍然觉得这个查询是不正确的。有没有更好的方法来编写这个查询

解决方法

这里有两个选项:

SELECT COUNT(*) FILTER (WHERE liked) - COUNT(*) FILTER (WHERE NOT liked)
FROM likes
WHERE post_id = 1;

SELECT SUM(CASE WHEN liked THEN 1 ELSE -1 END)
FROM likes
WHERE post_id = 1;
,

一般的解决方案是分两步进行聚合:

select max(cnt) - min(cnt)
from
(
  select count(*) cnt FROM likes WHERE post_id=1 GROUP BY liked
) dt

在您的情况下,只有两个不同的值可以使用条件聚合:

select abs(count(*) filter (where c1 = true) - count(*) filter (where c1 = false))
from b
WHERE post_id=1