[置顶] 子查询改为左链接

子查询是一个 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停止查找。

当通过t1扫描没有查找到t2记录时,t2.id自然为空,后面的where条件成立,返回的结果就是不在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成绩”进行排序.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值