子查询改为左链接

子查询是一个 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总成绩

 

在上面的示例中 SQL 语句的执行顺序如下:

(1). 首先执行 FROM 子句, tb_Grade 表组装数据源的数据

(2). 执行 WHERE 子句, 筛选 tb_Grade 表中所有数据不为 NULL 的数据

(3). 执行 GROUP BY 子句, tb_Grade 表按“学生姓名”列进行分组

(4). 计算 max() 聚集函数, “总成绩”求出总成绩中最大的一些数值

(5). 执行 HAVING 子句, 筛选课程的总成绩大于 600 分的.

(7). 执行 ORDER BY 子句, 把最后的结果按Max 成绩”进行排序.

 

猜你喜欢

转载自coollyj.iteye.com/blog/1832615
今日推荐