搜索不在关系中的多行n:m

juzqafwq  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(291)

类似的问题
与上面的问题非常相似,但有一点不同,我需要找到一个用户列表,这些用户在电影列表中至少没有看过一部电影。
假设有两个表'movies'和'users',它们之间有一个n:m关系,一个表'seen'描述了这种关系。
我需要找出任意数量的给定用户,以及任意数量的给定电影,所有的用户,从给定的列表中,至少没有看过一部给定电影。
这在一个查询中可以实现吗?我想不出一个办法。
编辑:这里有一个尝试解决这个问题的演示,问题是它返回的用户没有看到给定列表中的所有电影。我们需要的是没有看过该列表中任何电影的用户:http://rextester.com/deih39789

yfjy0ee7

yfjy0ee71#

这个查询应该会给出您想要的结果。我假设你的基本结构是:

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 ,和 u.id IN (userlist) 然后将结果仅限于该组用户。你可以修改 IN 与您感兴趣的电影和用户列表匹配的子句。我在rextester上做了一个小演示。
更新
我误解了这个问题;所需的结果适用于没有看过列表中一部(或多部)电影的用户。此查询解决了该问题:

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 以及 WHERE 是用户(1,2,3)和他们看过的电影。如果他们看过电影列表中的所有电影 (1, 2) ,的 COUNT 中的电影 seen 将是2,否则,如果他们没有看到一个(或多个),它将小于2。这是一个更新的演示。请注意,当电影列表的长度更改时 2HAVING 子句必须更改以匹配电影列表的长度。

cygmwpex

cygmwpex2#

我想说一些类似于左键将users表连接到seen表(并将该表连接到movies表)。
(根据matbailie的评论编辑了代码)
在join子句中添加list限制(而不是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。要知道,对于大型数据集(几千个并不算大),这个查询可能会变得很慢。为了测试它,我已经从seen列表中删除了“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) )
qzwqbdag

qzwqbdag3#

考虑用户和movies表之间的n:m关系,可以看到中间表。

SELECT * FROM Users u WHERE NOT EXISTS (SELECT UserId FROM Seen s WHERE s.UserId = u.ID)

此查询将返回在seen表中没有任何相关记录的用户

相关问题