使用 COUNT() 从 3 个连接表中获取数据

Using COUNT() to get data from 3 joined tables

我在 MySql 中有这 4 个表:

用户:

电影:

Collection(many-to-many用户与电影的关系):

评论:

所以基本上我想要的是从用户、评论和 collection 中提取数据并显示某种用户统计信息,例如 每个用户留下的评论数量,以及每个用户保存到他们 collection 的电影。我以为这只是 3 个表之间的简单连接,但显然我错了。

我认为使用 COUNT() 聚合函数是最好的主意,所以我开始分别查询 user-review 和 user-collection,效果很好,结果是查询正确。

 SELECT u.userID, username, COUNT(movieID) AS collection_size 
 FROM collection c INNER JOIN USER u ON u.userID=c.userID 
 GROUP BY c.userID


 userID username    collection_size
 7      user        2
 8      user03      6

SELECT u.userID, username, COUNT(movieID) AS review_count 
FROM review r INNER JOIN USER u ON u.userID=r.userID 
GROUP BY r.userID

userID  username    review_count
7       user        1
8       user03      4
10      user05      1

尝试连接所有三个表时出现问题。我最接近解决问题的是:

SELECT u.userID, username, COUNT(DISTINCT c.movieID) AS collection_size, COUNT(DISTINCT r.movieID) AS review_count
FROM collection c INNER JOIN USER u ON u.userID=c.userID 
INNER JOIN review r ON r.userID=u.userID
GROUP BY u.userID

userID  username    collection_size review_count
7       user        2               1
8       user03      6               4

结果几乎是正确的,但是如您所见,userID 为 10 的用户不见了,尽管他已经留下了一条评论。该查询似乎只提取至少留下一条评论 并且 在他们的 collection 中至少有一部电影的用户。我已经通过向用户 10 的 collection 添加电影来验证这一点。然后他正确地出现在结果中。 如何更改查询以显示至少留下一条评论的用户 OR 在他们的 collection?

中至少有一部电影

基本上我希望结果是这样的:

userID  username    collection_size review_count
7       user        2               1
8       user03      6               4
10      user05      0               1

该用户似乎没有 collection(您的第一个查询未返回)。您可以改用 LEFT JOINs,从用户 table:

开始
SELECT u.userID, u.username, 
    COUNT(DISTINCT c.movieID) AS collection_size, 
    COUNT(DISTINCT r.movieID) AS review_count
FROM usr u 
LEFT JOIN collection c ON u.userID=c.userID 
LEFT JOIN review r ON r.userID=u.userID
GROUP BY u.userID

虽然这有效,但效率不高。联接将两边的行相乘,然后计算不同的主键值。我认为用两个子查询来表达查询会更有效:

select u.userid, u.username, 
    (select count(*) from collection c where c.userid = u.userid) as collection_size,
    (select count(*) from review     r where r.userid = u.userid) as review_count
from usr u
SELECT
    a.userid
    ,b.qty_movies
    ,c.qty_reviews
FROM
    user a
    LEFT OUTER JOIN (
      SELECT
        userid
        ,COUNT(*) qty_movies
      FROM
        collection
      GROUP BY 1
    ) b ON (a.userid = b.userid)
    LEFT OUTER JOIN (
      SELECT
        userid
        ,COUNT(*) qty_reviews
      FROM
        review
      GROUP BY 1    
    ) c ON (a.userid = c.userid)
;

https://www.db-fiddle.com/f/fiiwTyoFEuspGyscAh23bG/1