我有两个表:“电影”和“用户”。两者之间存在n:m关系,描述用户观看过哪些电影。这用表格“ seen”描述。现在,我想为给定的用户找出他尚未看过的所有电影。我当前的解决方案是这样的:
SELECT * FROM movies WHERE movies.id NOT IN ( SELECT seen.movie_id FROM seen WHERE seen.user_id=123 )
这可以正常工作,但扩展性似乎不太好。有更好的方法吗?
这是不使用您显示的子查询方法来执行此查询的典型方法。这可以满足@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 (...)” 更好
NOT EXISTS
column NOT IN (...)
同样,您必须测试每个解决方案并比较结果以确保确定。 在不衡量性能的情况下选择任何解决方案都是浪费时间。