欢迎投稿

今日深度:

SQL点滴之性能优化其实没有那么神秘(1)(3)

5、 子查询的用法

子查询是一个 SELECT 查询,它嵌套在 SELECT、INSERT、UPDATE、DELETE 语句或其它子查询中。任何允许使用表达式的地方都可以使用子查询。

子查询可以使我们的编程灵活多样,可以用来实现一些特殊的功能。但是在性能上,往往一个不合适的子查询用法会形成一个性能瓶颈。如果子查询的条件中使用了其外层的表的字段,这种子查询就叫作相关子查询。相关子查询可以用IN、NOT IN、EXISTS、NOT EXISTS引入。

关于相关子查询,应该注意:

A、NOT IN、NOT EXISTS的相关子查询可以改用LEFT JOIN代替写法。比如:

  1. SELECT PUB_NAME 
  2. FROM PUBLISHERS 
  3. WHERE PUB_ID NOT IN 
  4.    (SELECT PUB_ID 
  5.    FROM TITLES 
  6.    WHERE TYPE = 'BUSINESS'
  7.             可以改写成: 
  8.  
  9. SELECT A.PUB_NAME 
  10. FROM PUBLISHERS A LEFT JOIN TITLES B 
  11. ON        B.TYPE = 'BUSINESS' AND 
  12.           A.PUB_ID=B.PUB_ID 
  13. WHERE B.PUB_ID IS NULL 
  14.   
  15.  
  16. SELECT TITLE 
  17. FROM TITLES 
  18. WHERE NOT EXISTS 
  19.    (SELECT TITLE_ID 
  20.    FROM SALES 
  21.    WHERE TITLE_ID = TITLES.TITLE_ID) 
  22.  
  23. 可以改写成: 
  24.  
  25. SELECT TITLE 
  26. FROM TITLES LEFT JOIN SALES 
  27. ON SALES.TITLE_ID = TITLES.TITLE_ID 
  28. WHERE SALES.TITLE_ID IS NULL 

B、 如果保证子查询没有重复 ,IN、EXISTS的相关子查询可以用INNER JOIN 代替。比如:

  1. SELECT PUB_NAME 
  2. FROM PUBLISHERS 
  3. WHERE PUB_ID IN 
  4.    (SELECT PUB_ID 
  5.    FROM TITLES 
  6.    WHERE TYPE = 'BUSINESS'
  7.  
  8. 可以改写成: 
  9.  
  10. SELECT DISTINCT A.PUB_NAME 
  11. FROM PUBLISHERS A INNER JOIN TITLES B 
  12. ON        B.TYPE = 'BUSINESS' AND 
  13.           A.PUB_ID=B.PUB_ID 

C、 IN的相关子查询用EXISTS代替,比如

  1. SELECT PUB_NAME 
  2. FROM PUBLISHERS 
  3. WHERE PUB_ID IN 
  4.    (SELECT PUB_ID 
  5.    FROM TITLES 
  6.    WHERE TYPE = 'BUSINESS'
  7.  
  8. 可以用下面语句代替: 
  9.  
  10. SELECT PUB_NAME 
  11. FROM PUBLISHERS 
  12. WHERE EXISTS 
  13.    (SELECT 1 
  14.    FROM TITLES 
  15.    WHERE TYPE = 'BUSINESS' AND 
  16.    PUB_ID= PUBLISHERS.PUB_ID) 

D、不要用COUNT(*)的子查询判断是否存在记录,最好用LEFT JOIN或者EXISTS,比如有人写这样的语句:

  1. SELECT JOB_DESC FROM JOBS 
  2. WHERE (SELECT COUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)=0 
  3.  
  4. 应该改成: 
  5.  
  6. SELECT JOBS.JOB_DESC FROM JOBS LEFT JOIN EMPLOYEE  
  7. ON EMPLOYEE.JOB_ID=JOBS.JOB_ID 
  8. WHERE EMPLOYEE.EMP_ID IS NULL 
  9.   
  10.  
  11. SELECT JOB_DESC FROM JOBS 
  12. WHERE (SELECT COUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)<>0 
  13.  
  14. 应该改成: 
  15.  
  16. SELECT JOB_DESC FROM JOBS 
  17. WHERE EXISTS (SELECT 1 FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID) 


www.htsjk.Com true http://www.htsjk.com/shujukugl/17764.html NewsArticle 5、 子查询的用法 子查询是一个 SELECT 查询,它嵌套在 SELECT、INSERT、UPDATE、DELETE 语句或其它子查询中。任何允许使用表达式的地方都可以使用子查询。 子...
评论暂时关闭