类似的问题here
与上述问题非常相似,但有一点点不同,我需要在电影列表中找到未曾看过至少一部电影的用户列表。
假设两个表“ movies”和“ users”之间存在一个n:m关系,一个表“ seen”描述了这种关系。
我需要从给定列表中找出任意数量的给定用户,以及任意数量的给定电影所有用户 ,但没有观看过至少一部电影。
在单个查询中可以实现吗?我不知道该怎么做。
编辑:这是一个尝试解决该问题的演示,所涉及的问题是它返回的用户尚未查看给定列表中的所有电影。我们需要的是一个从未观看过以下列表中的任何电影的用户:http://rextester.com/DEIH39789
答案 0 :(得分:1)
考虑“用户”和“电影”表之间的n:m关系,其中包含中间表。
SELECT * FROM Users u WHERE NOT EXISTS (SELECT UserId FROM Seen s WHERE s.UserId = u.ID)
此查询将返回在Seen表中没有任何相关记录的Users
答案 1 :(得分:1)
我想说些类似的方法,即将用户表左连接到可见表(并将该表连接到电影表)。
(由于MatBailie的评论而修改了代码)
在JOIN子句中添加列表限制(而不是MatBailie向我指出的WHERE子句),您会得到类似的信息(以下代码在SQL-Server上也应适用,但对MySql也应如此) ):
SELECT COUNT(Users.ID)
FROM Users
LEFT JOIN Seen ON Users.ID = Seen.UserID AND Users.something IN (list)
LEFT JOIN Movies ON Seen.MovieID = Movie.ID AND Movies.something IN (list)
WHERE Movies.ID IS NULL
GROUP BY User.ID -- <-- This is probably optional
但是由于通常有多种方法可以得到相同的结果,因此我以前的答案经过了调整:
SELECT COUNT(Users.ID)
FROM Users
LEFT JOIN Seen ON Users.ID = Seen.UserID
LEFT JOIN Movies ON Seen.MovieID = Movie.ID
WHERE (Users.something IN (list) OR Users.something IS NULL)
AND (Movies.something IN (list) OR Movies.something IS NULL)
AND Movies.ID IS NULL
GROUP BY User.ID -- <-- This is probably optional
第三次尝试:获取列表中已看过其中一部电影的所有用户ID。接下来,获取列表中的所有用户ID,并减去看过其中一部电影的用户ID。知道对于大数据集(几千个不大),此查询可能会变慢。为了测试它,我从看到的列表中删除了“ userid = 2和movieid = 3”,否则我不会得到结果。现在,我发现尼克没有看过前三部电影中的任何一部(请参考您的右摄示例)
SELECT *
FROM musers
WHERE musers.id IN (1,2,3)
AND musers.id NOT IN (
SELECT musers.id
FROM musers
JOIN Seen ON musers.ID = Seen.UserID
JOIN Movies ON Seen.MovieID = movies.ID
WHERE movies.id IN (1,2,3) )
答案 2 :(得分:1)
此查询应为您提供所需的结果。我假设您的基本结构是:
users (id int, name varchar(20));
movies (id int, title varchar(20));
seen (user_id int, movie_id int);
SELECT u.*
FROM users u
LEFT JOIN seen s
ON s.user_id = u.id AND s.movie_id IN (movielist)
WHERE s.user_id IS NULL AND u.id IN (userlist)
WHERE s.user_id IS NULL
条件意味着LEFT JOIN
为您提供了movielist
中没有看过电影的所有用户,而{{1} }然后将结果限制为仅该组用户。
您可以修改u.id IN (userlist)
子句以匹配您感兴趣的电影和用户列表。我制作了一个小的demo on Rextester。
更新
我误解了这个问题;对于没有看过列表中一部(或多部)电影的用户来说,理想的结果是。此查询解决了该问题:
IN
SELECT u.*
FROM musers u
LEFT JOIN seen s
ON s.user_id = u.id AND s.movie_id IN (1, 2)
WHERE u.id IN (1, 2, 3)
GROUP BY u.id
HAVING COUNT(s.movie_id) < 2
和JOIN
的结果是用户(1、2、3)和他们看过的电影。如果他们看过电影列表WHERE
中的所有电影,则(1, 2)
中电影的COUNT
为2,否则,如果他们没有看过一个(或多个)电影,小于2。这是updated demo。请注意,当电影列表的长度更改时,seen
子句中的2
必须更改以匹配电影列表的长度。