sql 来自多个表的 count()

sql count() from multiple tables

有这样的表格:

  1. 图片:

    wall_id|picture_id|user_id|likes
          1|         1|      1|    2
          1|         2|      1|    0
          2|         1|      1|    1
          2|         2|      2|    2
    

对 (wall_id, picture_id) 是唯一的

  1. 喜欢的人:

    wall_id|picture_id|user_id
          1|         1|      3
          1|         1|      2
          2|         1|      2
          2|         2|      4
          2|         2|      3
    

我想要这样的东西:

    user_id|pictures_count|likes_count|likers_count
          1|             3|          3|           2
          2|             1|          2|           2

我试过这个:

select p.user_id as user_id, 
    count(p.user_id) as pictures_count, 
    sum(p.likes) as likes_count, 
    count(distinct l.user_id) as likers_count
 from pictures p
 left join likers l on p.wall_id = l.wall_id 
                       and p.picture_id = l.picture_id
 group by p.user_id

select pictures.user_id, count(pictures.user_id) as pictures_count,
     sum(pictures.likes) as likes_count, 
    count(distinct likers.user_id) as likers_count 
from pictures, likers 
where pictures.picture_id = likers.picture_id 
    and pictures.user_id = likers.user_id 
group by pictures.user_id

但我得到这样的结果:

    user_id|pictures_count|likes_count|likers_count
          1|             4|          6|           2
          2|             2|          4|           2

我应该怎么做才能得到正确的结果?

A join 会导致行重复。您可以在加入之前应用聚合。

select  *
from    (
        select  wall_id
        ,       sum(likes) as likes_count
        ,       count(*) as picture_count
        from    pictures
        group by
                wall_id
        ) as pictures
left join
        (
        select  wall_id
        ,       count(distinct user_id) as likers_count
        from    likers
        group by
                wall_id
        ) as likes 
on      pictures.wall_id = likes.wall_id

Join 是奇怪的东西。当您有一个键并且多行在 both 边匹配时,您会得到更多您期望的行。解决方案是预先聚合每一侧的行。

这对于您的数据模型来说有点复杂,因为您需要 join 来查找 likes table.

的用户 ID
 select p.user_id as user_id, p.pictures_count, p.likes_count, l.likers_count
 from (select p.user_id, count(*) as pictures_count, sum(likes) as likes_count
       from pictures p
       group by p.user_id
      ) p left join
      (select p.user_id, count(distinct l.user_id) as likers_count
       from pictures p left join
            likers l
            on p.wall_id = l.wall_id and p.picture_id = l.picture_id
       group by p.user_id
      ) l
      on p.user_id = l.user_id;

请注意,因为聚合是在子查询中完成的,所以在外部查询中不再需要它。

试试这个:

SELECT T1.user_id,T1.pictures_count,T1.likes_count,T2.likers_count FROM
(select p.user_id,
       count(*) AS pictures_count,
       SUM(p.likes) as likes_count
from pictures p 
group by p.user_id) T1 JOIN

(select p.user_id,count(distinct l.user_id) as likers_count
from pictures p join
     likers l on p.wall_id = l.wall_id and p.picture_id = l.picture_id
group by p.user_id) T2 on T1.user_id=T2.user_id

结果:

USER_ID PICTURES_COUNT  LIKES_COUNT LIKERS_COUNT
1       3               3           2
2       1               2           2

SQL Fiddle 中查看结果。