设为首页 收藏本站
查看: 1194|回复: 0

[经验分享] sql 子查询和连接查询

[复制链接]

尚未签到

发表于 2018-10-17 13:32:12 | 显示全部楼层 |阅读模式
  子查询就是查询中又嵌套的查询,嵌套的级数随各数据库厂商的设定而有所不同,一般最大嵌套数不超过15级,实际应用中,一般不要超过2级,否则代码难以理解.一般来说,所有嵌套子查询都可改写为非嵌套的查询,但是这样将导致代码量增大.子查询就如递归函数一样,有时侯使用起来能达到事半功倍之效,只是其执行效率同样较低,有时用自身连接可代替某些子查询,另外,某些相关子查询也可改写成非相关子查询.
  子查询常用于复杂的SQL操作中,包括select,insert,delete,update等语句中都可嵌套子查询.子查询分为两种:相关子查询和不相关子查询,顾名思义,相关子查询不能独自运行,必须依赖于外部父查询提供某些值才能运行.
  子查询可以返回:结果集,逻辑值.仅当使用exists子句时,子查询才不返回结果集,而只返回true或false这样的逻辑值.可用于子查询的关键字有:IN,ANY(任一),ALL等.具体的说,子查询可返回单值,元组(即两个或两个以上值),及多值结果集.
  下面举一些例子来说明子查询的使用:
  1. 假设数据表emp中有empID和empName两个字段,其中empID(主键)有重复,现在要求删除表中empID值有重复的记录,并且必须保留一条empID值重复的记录.
  解决思路:用相关子查询和自身连接即可,下面是实现的SQL语句
  Delete from emp e1 where empID in ( select empID from emp where empID = e1.empID and empName != e1.empName )
  2. 用子查询来更新数据库表.假设数据表salary中有2个字段empID和salaryAmount,数据表emp中有2个字段empID和Age,请用emp表中的Age字段来代替salary表中的salaryAmount字段的值,下面是实现的SQL语句
  Update salary S Set salaryAmount = ( select Age from emp where empID = S.empID )
  说明:在(相关)子查询中也可使用未出现在父查询中的字段值,如上例中的empID字段
  3. 连接:连接分为4种,分别是内连接(inter join),外连接(outer join,分为左,右和全外连接三种),交叉连接(cross join)和自身连接(self join).外连接的关键字和标识符有:left,right,full,(+),*等.当为(+)标识时,则靠近(+)的表为副表,而远离(+)的表则为主表(这依赖于数据库实现,在Oracle中是这样规定的 )
  4. 假设有客户表customer,其中字段有custID,custName,Addr,客户定货表orders,其中字段有       orderID,custID,orderDate,procID.请查询出在2000年1月1日以后有订货的客户及(没有订货的)所有客户
  Select custID,custName,Addr,orderDate from customer left join orders on
  (customer.custID = orders.custID) and ( orderDate >'2000-1-1')
  说明:左外连接,则左边的表为主表,在本例中,表customer即为主表;右外连接,则右边的表即为主表. 若不用坐外连接,则2000年1月1日前未订货的客户则查询不出来.一般来说,如果要使查询中不遗漏任何记录,则只有用全外连接(full outer join)才行.
  5. 查询的6个关键字有:select,from,where,group by,having,order by,以上是它们在查询语句中一般应出现的顺序.having与group by的关系就犹如where 与select的关系一样,都是用于限定哪些行被选中.以下是一些注意事项:
  子查询中不能排序,即不能有order by子句
  order by子句中的字段可以不出现在select子句后的字段列表中,但但当有distinct限定词时,order by中的字段必须出现在select子句中.
  子查询可以嵌套,并且是从里往外开始执行
  6.假设有学生表student,其中有字段sno,sname,birthday,课程表course,其中有字段cno,cname,ccent,学生选课表sc,其中有字段cno,sno,grade
  请查询出未选修任何课的学生
  select sno,sname from student S where not exists
  ( select sno from sc where cno in
  ( select cno from course where cno = sc.cno and sc.sno = s.sno )
  )
  查询出未被任何学生选修的课程号及课程名
  select cno,cname from course where cno not in ( select cno from sc )
  删除未被任何学生选修的课程
  delete from course where cno in ( select cno from course where cno not in
  ( select cno from sc )
  )
  7.并union,交intersect,差minus运算
  请查询出同时选修了2门以上课程的学生名单,如英语和汉语
  select * from student where sno in
  ( select sno from sc
  where cno in
  ( select cno from course where cname ='英语' )
  )
  union
  select * from student where sno in
  ( select sno from sc
  where cno in
  ( select cno from course where cname ='汉语' )
  )
  查询出选修了英语而未选修汉语的学生名单
  select * from student where sno in
  ( select sno from sc
  where cno in
  ( select cno from course where cname ='英语' )
  )
  minus
  select * from student where sno in
  ( select sno from sc
  where cno in
  ( select cno from course where cname ='汉语' )
  )
  查询出既选修了英语又选修了汉语的学生名单
  select * from student where sno in
  ( select sno from sc
  where cno in
  ( select cno from course where cname ='英语' )
  )
  intersect
  select * from student where sno in
  ( select sno from sc
  where cno in
  ( select cno from course where cname ='汉语' )
  )
  8.删除或修改子句不能加join条件,如:delete from table1 where condition1 and condition2 类似这样的语句不合法,即condition1条件后不能有condition2或更多的条件,解决的办法可以用子查询,如:
  delete from table1 where ( ... ),同样,对update 子句也类似
  9.内连接是等值连接,所以当两个表间不匹配时,很容易遗漏数据,解决的办法是用外连接,但无论是左外连接还是右外连接,在理论上都只能使遗漏的数据少些,只有全外连接才能保证不遗漏数据.
  需要注意NULL(空值)对(子)查询的影响,比如下例,如要查询出A和B表中存在相同ID的等级时,就必须限定ID不为NULL,否则子查询返回空结果集:
  select A.ID,A.Level,A.desc from table1 A
  where A.Level in
  ( select B.Level from table2 B where
  ( A.ID = B.ID and B.ID is not null )
  )


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-622863-1-1.html 上篇帖子: SQL*PLUS的异常处理-SP2-0606 下篇帖子: MySQL SQL常用语句自我测试练习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表