仅考虑具有特定条目的项目来聚合表的有效方式

时间:2013-08-13 17:39:38

标签: sql postgresql

抱歉这个笨重的头衔。一个例子可以解释。

假设我有一个喜欢的表,每个表都有一个条目

user_id  |  liked_id
--------------------
   1     |     a
   2     |     a
   1     |     b
   2     |     c

含义用户1喜欢商品ab,而用户2喜欢商品ac

要获得每件商品的总计数,我可以这样做:

SELECT liked_id, COUNT(*)
  FROM likes
  GROUP BY liked_id

但是,对于特定用户喜欢的项目,是否有一种很好的方式可以 ?因此,例如,查询用户1,我想要的结果是:

liked_id |  count
------------------
   a     |    2
   b     |    1

因为用户1喜欢的是商品ab,而不是c

我能想到的最好的是带有子选择的JOININ

SELECT l.liked_id, count(*)
  FROM likes l
    JOIN (
      SELECT liked_id
        FROM likes
        WHERE user_id = 1
      ) l2
      ON l.liked_id=l2.liked_id
  GROUP BY l.liked_id;

汇总时是否有更好的方法可以推广?我觉得我可以做一些HAVING诡计,但也许不行,无论如何它可能是一个较慢的解决方案。

编辑:如果标签没有明确说明,我正在使用Postgres。

编辑:感谢所有的答案,我接受了我认为最好和最快的,因为我问了一个问题 - 应该是显而易见的,真的,但是我给了每个人一个+1。

我应该提到我需要来自相似表中条目的另一条数据,以便我可以稍后订购。子选择将按照已接受的答案进行自我加入,并在SELECTGROUP BY部分中添加其他条目。这会教我过分简化一些问题......谢谢!

4 个答案:

答案 0 :(得分:2)

您可以尝试以下内容:

SELECT liked_id, COUNT(*)
  FROM likes
 GROUP BY liked_id
HAVING count(case when user_id = 1 then 1 end) > 0;

count(case when user_id = 1 then 1 end)将计算user_id = 1喜欢特定liked_id的次数。

此查询将在一次完整扫描中获得结果。它将比2次完整扫描更快,但可能比2次索引扫描慢(如果您的索引位于liked_iduser_id)。

答案 1 :(得分:1)

使用EXISTS

SELECT  L.LIKED_ID
        ,COUNT(L.USER_ID) AS USER_COUNT
FROM    LIKES L
WHERE   EXISTS (SELECT  1 
                FROM    LIKES L2 
                WHERE   L2.LIKED_ID = L.LIKED_ID 
                AND L2.USER_ID = 1
                )
GROUP BY 
        L.LIKED_ID

答案 2 :(得分:1)

根据我的理解,这应该有效,您需要获得仅被count

所喜欢的user个喜欢的项目
SELECT 
  liked_id, 
  COUNT(*)
FROM 
  likes l
WHERE
  EXISTS ( SELECT 1 FROM likes WHERE user_id = 1 AND like_id = l.id )
GROUP BY 
  liked_id

答案 3 :(得分:1)

当然:加入桌子:

SELECT t1.liked_id, COUNT(*)
FROM likes t1
JOIN likes t2 on t2.liked_id = t1.liked_id
WHERE t1.user_id = 1
GROUP BY t1.liked_id

这不仅是一种优雅的编码方式,它也是性能最佳的,只要liked_id上有一个索引用于连接性能,而user_id上的索引用于查找性能