一尘不染

MySQL:查找不参与关系的行

mysql

我有两个表:“电影”和“用户”。两者之间存在n:m关系,描述用户观看过哪些电影。这用表格“
seen”描述。现在,我想为给定的用户找出他尚未看过的所有电影。我当前的解决方案是这样的:

SELECT *
FROM movies 
WHERE movies.id NOT IN (
     SELECT seen.movie_id 
     FROM seen 
     WHERE seen.user_id=123
)

这可以正常工作,但扩展性似乎不太好。有更好的方法吗?


阅读 234

收藏
2020-05-17

共1个答案

一尘不染

这是不使用您显示的子查询方法来执行此查询的典型方法。这可以满足@Godeke的要求,以查看基于联接的解决方案。

SELECT * 
FROM movies m
 LEFT OUTER JOIN seen s
 ON (m.id = s.movie_id AND s.user_id = 123)
WHERE s.movie_id IS NULL;

但是,在大多数品牌的数据库中,此解决方案的性能可能比子查询解决方案差。最好使用EXPLAIN来分析两个查询,以查看在您的模式和数据下哪个查询会更好。

这是子查询解决方案的另一个变体:

SELECT * 
FROM movies m
WHERE NOT EXISTS (SELECT * FROM seen s 
                  WHERE s.movie_id = m.id 
                    AND s.user_id=123);

这是一个相关的子查询,必须为外部查询的每一行进行评估。通常这很昂贵,并且您的原始示例查询更好。另一方面,在MySQL中,“ NOT EXISTS”通常比“ column NOT IN (...)” 更好

同样,您必须测试每个解决方案并比较结果以确保确定。 在不衡量性能的情况下选择任何解决方案都是浪费时间。

2020-05-17