2014-03-31 34 views
2

比方说,我们有一个数据库,记录用户尚未评分的所有电影。每个评级都记录在一个MovieRating表格中。NOT IN查询有哪些替代方法?

当我们正在寻找电影的用户#1234还没有见过的:

SELECT * 
FROM Movies 
WHERE id NOT IN 
    (SELECT DISTINCT movie_id FROM MovieRating WHERE user_id = 1234); 

查询NOT IN可以像MovieRating的规模增长非常昂贵。假设MovieRatings可以有100,000多行。

我的问题是什么是一些更有效的替代NOT IN查询?我听说过LEFT OUTER JOIN和NOT EXIST查询,但还有其他什么吗?有什么办法可以设计不同的数据库吗?

+2

什么是您的DBMS? (还提到你不想'JOIN'查询 - 但它是一个选项) –

+0

你正在假设一个特定的执行策略。例如,SQL Server不关心你如何编写这个查询。 – usr

+0

Postgres,但我愿意使用其他任何东西,包括nosql或图形数据库 - 只要它可以解决这个问题:) – user3481946

回答

0

的相关使用WHERE NOT EXISTS子查询()是潜在的最有效的,如果你要做到这一点,但你应该对测试数据的性能。

您可能还想考虑限制您的结果在选择列表(不使用*)和只有TOP n行。也就是说,如果用户没有看到他们,你可能不需要100k +电影。您可能想要分页结果。

SELECT * 
    FROM Movies m 
WHERE NOT EXISTS (SELECT 1 
        FROM MovieRating r 
        WHERE user_id = 1234 
         AND r.movie_id= m.movie_id) 
+0

这确实是我需要的最快的。谢谢。 – user3481946

0

这是一个模拟查询,因为我没有一个db来测试这个,但是沿着应该是工作。

select m.* from Movies m 
left join MovieRating mr on mr.user_id = 1234 
where mr.id is null 

应该根据用户ID将电影表加入电影分级表。 where子句然后将查找空条目,这将是用户未评级的电影。

+0

左连接是否先通过所有行?如果这样,复杂度/执行时间与MovieRating的大小成线性增长? – user3481946

+0

复杂性不会增长,但它与使用的数据库引擎无关,SQL Server,MySQL,Oracle等等......随着数据库的增长,查询将花费更长的时间(稍微长一点,除非您处理的是超大型数据库,100,000K行不是那么大) – mituw16

+0

如果MovieRating.USER_ID =上有一个索引,那么它就会寻找这些行,将它们加入到Movies中,然后返回NULL行作为结果集。 –

0

你可以试试这个:

SELECT M.* 
    FROM Movies as M 
     LEFT OUTER JOIN 
     MovieRating as MR on M.id = MR.movie_id 
         and MR.user_id = 1234 
WHERE M.id IS NULL 
+0

“内连接”永远不会返回结果。 – mituw16

+0

我知道..这不是一个内部连接:P –

相关问题