2014-11-03 45 views
1

我谁是一组(课堂)的一部分,由学生做练习提交的名单,这包含:优化MySQL查询嵌套不存在可能吗?

submission table: userId, groupId, exercise_id (and more irrelevant data) 
users table: userId, groupId 

我想选择所有的学生在一个特定群体所做的所有练习。为此,我目前有:

SELECT DISTINCT(exercise_id) FROM submissions as c1 WHERE c1.groupId = 1 
AND NOT EXISTS(
    SELECT DISTINCT(UserId) FROM users as u WHERE u.GroupId = 1 
    AND NOT EXISTS (
     SELECT exercise_id FROM submissions as c2 WHERE u.UserId = c2.UserId 
     AND c2.exercise_id = c1.exercise_id 
    ) 
) 

即我选择所有这些有那些尚未行使组在没有用户的练习。

但是,此查询在包含150万行的提交表上需要5秒。我可以采取哪些步骤来进一步优化此查询?我已经考虑了内部连接,但不会导致相同的查询执行计划?

回答

1

groupid确实不应该在两个表中。假设值是一致的,请尝试以下操作:

select s.exercise_id 
from submissions s 
where s.groupid = 1 
group by s.exercise_id 
having count(distinct userid) = (select count(distinct userid) from users where groupid = 1); 

出于性能考虑,你想对submissions(groupid, exercise_id)的索引。此外,如果您知道没有重复的提交或用户,请删除distinct,因为这会对性能产生不利影响。

+0

与我的查询相比,此功能非常快速。你有没有一个结构化的方式来提出它? – Bas 2014-11-03 12:46:56

+1

@Bas。 。 。你的问题是一种“set-set-set”查询,我通常使用聚合和“having”子句来处理这些问题(我应该注意:总是记录,但通常是)。 – 2014-11-03 12:54:49