可以EXISTS使这个查询更有效吗?

时间:2011-05-31 14:15:21

标签: sql select exists

我想只检索具有不可接受成绩的学生。我的原始查询是:

SELECT ssm.STUDENT_ID,COUNT(srcg.GRADE_TITLE) AS POSTED_GRADES
    FROM STUDENT_ENROLLMENT ssm, STUDENT_REPORT_CARD_GRADES srcg
    WHERE ssm.SYEAR='2010' 
    AND ssm.SCHOOL_ID='12' 
    AND ssm.GRADE_ID IN ('140','141','142','143','144','145')
    AND srcg.STUDENT_ID=ssm.STUDENT_ID 
    AND srcg.SYEAR='2010' 
    AND srcg.SCHOOL_ID='12' 
    AND srcg.MARKING_PERIOD_ID='434' 
    AND srcg.GRADE_TITLE IN ('1','2','F','D')               
    GROUP BY ssm.STUDENT_ID;

但我不关心伯爵;我只想找到成绩不好的学生。我正在尝试另一个查询:

SELECT ssm.STUDENT_ID
    FROM STUDENT_ENROLLMENT ssm
    WHERE ssm.SYEAR='2010' 
    AND ssm.SCHOOL_ID='12' 
    AND ssm.GRADE_ID IN ('140','141','142','143','144','145')
    AND EXISTS(SELECT srcg.GRADE_TITLE from STUDENT_REPORT_CARD_GRADES srcg, STUDENT_ENROLLMENT ssm
    WHERE srcg.STUDENT_ID=ssm.STUDENT_ID 
    AND srcg.SYEAR='2010' 
    AND srcg.SCHOOL_ID='12' 
    AND srcg.MARKING_PERIOD_ID='434' 
    AND srcg.GRADE_TITLE IN ('1','2','F','D'));

但它会返回更多记录,所以显然我做错了。有没有办法使用EXISTS,它将返回与第一个查询相同的结果但效率更高?

5 个答案:

答案 0 :(得分:0)

您可以获得更多记录,因为您没有像使用GROUP BY的第一个查询中那样删除重复项。重新放入GROUP BY,或添加DISTINCT,看看它是如何运作的。

答案 1 :(得分:0)

您可以删除exists子句中的student_enrollment连接。

 SELECT ssm.STUDENT_ID, COUNT(*) AS POSTED_GRADES
   FROM STUDENT_ENROLLMENT ssm
  WHERE ssm.SYEAR = '2010' 
    AND ssm.SCHOOL_ID = '12' 
    AND ssm.GRADE_ID IN ('140','141','142','143','144','145')
    AND EXISTS(SELECT srcg.GRADE_TITLE 
                 from STUDENT_REPORT_CARD_GRADES srcg
                WHERE srcg.SYEAR = '2010' 
                  AND srcg.SCHOOL_ID = '12' 
                  AND srcg.MARKING_PERIOD_ID = '434' 
                  AND srcg.GRADE_TITLE IN ('1','2','F','D')
              );
GROUP BY ssm.STUDENT_ID

如果STUDENT_REPORT_CARD_GRADES表很大,这可能会更快。

答案 2 :(得分:0)

我长期以来一直不喜欢“与众不同”,因为它过去曾隐藏过我的错误。我推荐这个:

select STUDENT_ID from 
(SELECT ssm.STUDENT_ID,COUNT(srcg.GRADE_TITLE) AS POSTED_GRADES
    FROM STUDENT_ENROLLMENT ssm, STUDENT_REPORT_CARD_GRADES srcg
    WHERE ssm.SYEAR='2010' 
    AND ssm.SCHOOL_ID='12' 
    AND ssm.GRADE_ID IN ('140','141','142','143','144','145')
    AND srcg.STUDENT_ID=ssm.STUDENT_ID 
    AND srcg.SYEAR='2010' 
    AND srcg.SCHOOL_ID='12' 
    AND srcg.MARKING_PERIOD_ID='434' 
    AND srcg.GRADE_TITLE IN ('1','2','F','D')               
    GROUP BY ssm.STUDENT_ID);

答案 3 :(得分:0)

根据我的经验,如果您对效率感兴趣,则不应该使用EXISTS。请尝试以下方法:

SELECT DISTINCT ssm.STUDENT_ID
FROM STUDENT_ENROLLMENT ssm
INNER JOIN STUDENT_REPORT_CARD_GRADES srcg
  ON (srcg.STUDENT_ID = ssm.STUDENT_ID)
WHERE ssm.SYEAR='2010' AND
      ssm.SCHOOL_ID = '12' AND
      ssm.GRADE_ID IN ('140','141','142','143','144','145') AND
      srcg.SYEAR='2010' AND
      srcg.SCHOOL_ID = '12' AND
      srcg.MARKING_PERIOD_ID = '434' AND
      srcg.GRADE_TITLE IN ('1','2','F','D')

确保您在以下字段或字段组中包含索引:

  • STUDENT_ENROLLMENT(student_id数据)
  • STUDENT_ENROLLMENT(SYEAR,SCHOOL_ID,GRADE_ID)
  • STUDENT_REPORT_CARD_GRADES(student_id数据)
  • STUDENT_REPORT_CARD_GRADES(SYEAR,SCHOOL_ID,MARKING_PERIOD_ID,GRADE_TITLE)

另外,请确保您使用的常量与所涉及的列的数据类型相匹配。此语句中的所有常量都以字符串形式给出 - 所有字段都是字符列,还是数字(例如,STUDENT_ENROLLMENT.SYEAR)?强制数据库执行不必要的转换会导致它执行一些真正可怕的事情,例如将数字列值转换为字符串,以便将转换后的列值与字符串常量进行比较。这可以保证表扫描速度非常慢,性能可怕。

分享并享受。

答案 4 :(得分:0)

尝试这个

    SELECT distinct ssm.STUDENT_ID
    FROM STUDENT_ENROLLMENT ssm, STUDENT_REPORT_CARD_GRADES srcg
    WHERE ssm.SYEAR='2010' 
    AND ssm.SCHOOL_ID='12' 
    AND ssm.GRADE_ID IN ('140','141','142','143','144','145')    
    AND srcg.STUDENT_ID=ssm.STUDENT_ID 
    AND srcg.SYEAR= ssm.SYEAR 
    AND srcg.SCHOOL_ID=ssm.SCHOOL_ID
    AND srcg.MARKING_PERIOD_ID='434' 
    AND srcg.GRADE_TITLE IN ('1','2','F','D')