sql数据库开发-8:多表查询时,常用的子查询

多表查询时,常用的子查询

 

非关联子查询


     子查询的应用场景

    问题

      --哪些os账户的开通时间是最早的。

    核心点

      --如果能获得最早的开通时间,根据该结果很容易得到哪些os账号

    解决方法

      -- 使用子查询

 


子查询

    子查询就是在一条SQL语句中嵌入SELECT语句

子查询语法:

    select colname1,... ... from tabname where expr operator (select colname2 from subtabname);

 

 

子查询的执行过程

      先执行子查询,子查询的返回结果作为主查询的条件,再执行主查询。

      子查询只执行一遍。

      如子查询的返回结果为多个值,ORACLE会去掉重复之后,再将结果返回给主查询。

 


项目案例:

  哪些os账号的开通时间是最早的。


项目案例:

  哪些os账号的开通时间比unix服务器192.168.0.26上的huangr晚

项目案例:

   哪些os账号的开通时间比huangr晚。()多台unix服务器上都有名为huangr的os账号)

 

 


子查询常见错误

    单行子查询返回多条记录。


  select colname1,... ... from tabname where expr = (select colname1 from subtabname
 where condition1);


 ORA-01427:single-row subquery returns more than one row

 

 


子查询的注意事项

   比较运算符的选择

   若子查询的返回结果仅为一个值,可以用单值运算符 如 = 等

   若子查询的返回结果可能为多值,必须用多值运算符如 IN 等。

 

 


项目案例:

   哪些客户是推荐人
 
   哪些客户不是推荐人

 


子查询与空值

  若子查询的返回结果中包含空值(NULL) ,并且运算符为 NOT IN,那么整个查询不会返回任何行。NOT IN 等价于<>ALL,任何值跟NULL比(包括NULL本身),结果都不为true

 
  select colname from tabname where colname not in (select colname from subtabname);
 

   no rows selected .

 

 


多列子查询


     where 子句后面可以跟多列条件表达式

   select colname1,... ...  from tabname where (colname1,colname2) IN (select colname1,AVG(colname2) from subtabname group by colname1);

 

 

项目案例:

   哪些os账号的开通时间是所在unix服务器上最早的?(每台unix服务器上最早开通的os账号)

   哪些os账号的开通时间比所在的unix服务器上最早的开通时间晚九天。

   哪些os账号的开通天数等于同一台unix服务器上的平均开通天数。

 

 

 

关联子查询


   关联子查询的应用场景

 
   问题
 
      --  哪些os账号的开通天数比同一台unix服务器上的平均开通天数长。

   核心点

      --  该问题的难点是同一台unix服务器的平均开通天数,如何表达同一台unix服务器是解决该问题的核心。

   解决方法

      --  使用关联子查询      

 

 

 

关联子查询

     关联子查询的语法形式

      select colname1,colname2,... from table1 o where colname1 orerator (select colname1,colname2 from table2 i where i.expr1 = o.expr2);

 

 

 

项目案例:

     哪些os账号的开通天数比同一台unix服务器上的平均开通天数长 。

 

 


关联子查询的执行过程

   关联子查询采用的是循环 (loop)的方式,执行步骤如下:

 
 
1.外部查询 得到一条记录(查询先从outer表中读取数据) 并将其传入到内部查询;


2.内部查询基于传入的值执行;

3.内部查询从其结果中包值传回到外部查询,外部查询使用这些值来完成其处理,如符合条件,outer表中得到的那条记录就放入结果集中,否则放弃,该记录不符合条件。

4.重复执行步骤1-3, 直到把outer表中的所有记录判断一遍。

 


项目案例:

    哪些客户是推荐人
 
        

 

EXISTS的执行过程


    EXISTS采用的是循环(loop) 方式,判断outer表中是否存在记录只要在inner表中找到一条匹配的记录即可。


1.外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表。


2.对inner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回true,将outer表中的记录放入结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回false,outer表中的该记录被过滤掉,不能出现在结果集中。


3.重复执行步骤1-2,直到把outer表中的所有记录判断一遍。

 

 

 

项目案例:

   哪些客户申请了远程登录业务

 

 


NOT EXISTS 的执行过程


NOT EXISTS采用的是循环(loop) 方式,判断在outer表中是否不存在记录,它能在inner表中能找到匹配的记录。

 

1.外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表。


2.对inner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回false,outer表中的该记录被过滤掉,不能出现在结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回true,将outer表中的记录放入结果集中。


3.重复执行步骤1-2,直到把outer表中的所有记录判断一遍。

 

 


项目案例:

    哪些客户不是推荐人

    哪些客户没有申请远程登录业务

 

 

IN和EXISTS的比较


   EXISTS是用循环(loop)的方式,由outer表的记录数决定循环的次数,对于exists影响最大,所以,外部的记录数要少。

   IN先执行子查询,子查询的返回结果去重之后,再执行主查询,所以,子查询的返回结果越少,越适合用该方式

 

 

 

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕容屠苏

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值