日期:2014-05-16  浏览次数:20564 次

子查询改为左链接

子查询是一个 SELECT 查询,它嵌套在 SELECT、INSERT、UPDATE、DELETE 语句或其它子查询中。
  任何允许使用表达式的地方都可以使用子查询,子查询可以使我们的编程灵活多样,可以用来实现一些特殊的功能。但是在性能上,往往一个不合适的子查询用法会形成一个性能瓶颈。如果子查询的条件中使用了其外层的表的字段,这种子查询就叫作相关子查询。


相关子查询可以用IN、NOT IN、EXISTS、NOT EXISTS引入。 关于相关子查询,应该注意:
(1) NOT IN、NOT EXISTS的相关子查询可以改用LEFT JOIN代替写法。比如:

SELECT PUB_NAME FROM PUBLISHERS WHERE PUB_ID NOT IN (SELECT PUB_ID FROM TITLES WHERE TYPE ='BUSINESS')

可以改写成:
SELECT A.PUB_NAME FROM PUBLISHERS A LEFT JOIN TITLES B ON B.TYPE ='BUSINESS'AND A.PUB_ID=B. PUB_ID WHERE B.PUB_ID IS NULL
  
比如NOT EXISTS:
SELECT TITLE FROM TITLES? WHERE NOT EXISTS? (SELECT TITLE_ID FROM SALES WHERE TITLE_ID = TITLES.TITLE_ID)
可以改写成:
SELECT TITLE? FROM TITLES LEFT JOIN SALES? ON SALES.TITLE_ID = TITLES.TITLE_ID? WHERE SALES.TITLE_ID ISNULL

2)如果保证子查询没有重复 ,IN、EXISTS的相关子查询可以用INNER JOIN 代替。比如:
SELECT PUB_NAME? FROM PUBLISHERS? WHERE PUB_ID IN? (SELECT PUB_ID? FROM TITLES? WHERE TYPE ='BUSINESS')
可以改写成:
SELECT DISTINCT A.PUB_NAME? FROM PUBLISHERS? A JOIN TITLES? B ON A. PUB_ID=B. PUB_ID WHERE B. TYPE ='BUSINESS'

?

  • ?LEFT JOIN 和 is null 的理解

SELECT *? from? t1? ?LEFT JOIN t2?? ON?? t1.id=t2.id???? WHERE t2.id IS NULL;
假定t2.id定义为NOT NULL。在这种情况下,MySQL使用t1.id的值扫描t1并查找t2中的行。
如果MySQL在t2中发现一个匹配的行,它知道t2.id绝不会为NULL,并且不再扫描t2内有相同的id值的行。
换句话说,对于t1的每个行,MySQL只需要在t2中查找一次,无论t2内实际有多少匹配的行。
当通过t1扫描查找到t2记录时,后面的where条件不成立,所以t1停止查找。返回的结果就是不在t2中的记录。

  • 查询逻辑顺序

在学生成绩表中 (暂记为 tb_Grade), “考生姓名”内容不为空的记录按照“考生姓名”分组, 并且筛选分组结果, 选出“总成绩”大于 600 分的,标准顺序的 SQL 语句为:

select 考生姓名, max(总成绩) as max总成绩

from tb_Grade

where 考生姓名 is not null

group by 考生姓名

having max(总成绩) > 600

order by max总成绩

?