使用 COUNT() 从 3 个连接表中获取数据
Using COUNT() to get data from 3 joined tables
我在 MySql 中有这 4 个表:
用户:
- 用户ID
- 用户名
- 密码
- 一些其他的东西
电影:
- 电影ID
- 名字
- 一些其他的东西
Collection(many-to-many用户与电影的关系):
- 用户ID
- 电影ID
评论:
- 评论ID
- 用户ID
- 电影ID
- 一些其他的东西
所以基本上我想要的是从用户、评论和 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 JOIN
s,从用户 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)
;
我在 MySql 中有这 4 个表:
用户:
- 用户ID
- 用户名
- 密码
- 一些其他的东西
电影:
- 电影ID
- 名字
- 一些其他的东西
Collection(many-to-many用户与电影的关系):
- 用户ID
- 电影ID
评论:
- 评论ID
- 用户ID
- 电影ID
- 一些其他的东西
所以基本上我想要的是从用户、评论和 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 JOIN
s,从用户 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)
;