(Les17 Retrieving Data Using Subqueries)[20180103]

2018-01-05 19:43:34来源:cnblogs.com作者:请点..头像人点击

分享
学习目标:    -多列子查询    -SQL语句中使用标量子查询    -更新或删除行使用关联子查询    -使用EXISTS和NOT EXISTS操作符    -使用WITH子句 多列子查询    语法:        Main query            WHERE (<column_name>,<column_name>) IN Subquery;     列的比较        -非成对比较(两两比较)        -成对比较        
    非成对比较                SELECT <column>,[<column>,| <column>]                FROM <table_name>                WHERE <column> IN Subquery                AND <column> IN Subquery;        成对比较                SELECT <column>,[<column>,|<column>]                FROM <table_name>                WHRE (<column>,<column>) IN                    (SELECT <column>,<column> FROM <table_name>                      WHERE clause);

                

    标量子查询        -标量子查询表达式中的子查询返回一个值        -标量子查询表达式中可以含有decode和case函数        -标量子查询中需排除GROUP BY        -标量子查询可以在UPDATESQL语句SET子句中和WHERE条件                标量子查询不能用于:            -列的默认值和集群的散列表达式            -DML语句RETURNING条件中            -基于函数的索引            -GROUP BY子句、CHECK约束和WHEN子句            -CONNECT BY子句            -与查询无关的语句中,如CREATE PROFILE概要文件                   
    例子:                SELECT <column>,<column>                    (CASE                         WHEN <column> = (SELECT <column>                                                             FROM <table_name>                                                            WHERE clause)                         THEN 'expression' END) <column_alias>                 FROM <table_name>; 

  

    关联子查询        -子查询引用主查询语句中的列值,Oracle执行相关子查询。        -对于主查询中的每一行,相关的子查询都会执行一次。        -主查询可以是SELECT/UPDATE或DELETE语句。         Nested Subqueries(嵌套子查询)或Correlated Subqueries(关联子查询)                -嵌套子查询:子查询首先运行并执行一次,返回结果给主查询。                -关联子查询:关联子查询由外部的主查询驱动的,所以主查询中的每个列值子查询均会执行一次。                                嵌套子查询执行顺序:                    -子查询执行一次并且返回一个值                    -主查询使用子查询返回的值执行一次                关联子查询执行顺序:                    -主查询候选列值                    -子查询使用主查询候选的列值运行并执行                    -子查询值返回给主查询                    -重复以上过程,直到没有候选列值                    
    SELECT <columu1>,<column2>,....                    FROM <table_name> outer                    WHERE <column1> operator                                    (SELECT <column1>,<column2>                                       FROM <table_name>                                       WHERE expr1 = outer.expr2);
                    注意:关联子查询中可以使用ANY和ALL操作符                    
关联子查询效能验证与可替换方式:
16:32:16 SQL> col last_name format a3016:32:16 SQL> set pagesize 120016:32:16 SQL> select last_name,salary,department_id16:32:16 2 from employees outer16:32:16 3 where salary >(select avg(salary)16:32:16 4 from employees16:32:16 5 where department_id=outer.department_id)16:32:16 6 ;LAST_NAME SALARY DEPARTMENT_ID------------------------------ ---------- -------------Hartstein 12990 20Raphaely 10990 30Weiss 7990 50Fripp 8190 50Kaufling 7890 50Vollman 6490 50Mourgos 5790 50Ladwig 3590 50Rajs 3490 50Sarchand 4190 50Bull 4090 50Chung 3790 50Dilly 3590 50Bell 3990 50Everett 3890 50
语句改写:
col last_name format a30set pagesize 1200select last_name,salary,department_idfrom employees outerwhere salary >(select avg(salary) from employees where department_id=outer.department_id) minus select outer.last_name,outer.salary,outer.department_idfrom employees outer,(select department_id,avg(salary) avg_salary from employees group by department_id) innerwhere outer.department_id=inner.department_idand outer.salary>inner.avg_salary; 对比两种写法: 16:45:11 SQL> set autotrace traceonly16:45:21 SQL> alter system flush shared_pool;已更改系統.16:45:22 SQL> select last_name,salary,department_id16:45:22 2 from employees outer16:45:22 3 where salary >(select avg(salary)16:45:22 4 from employees16:45:22 5 where department_id=outer.department_id); --关联子查询已選取 38 個資料列.執行計畫---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=11 Card=17 Bytes=6 97) 1 0 MERGE JOIN (Cost=11 Card=17 Bytes=697) 2 1 SORT (JOIN) (Cost=5 Card=11 Bytes=286) 3 2 VIEW OF 'VW_SQ_1' (VIEW) (Cost=5 Card=11 Bytes=286) 4 3 HASH (GROUP BY) (Cost=5 Card=11 Bytes=77) 5 4 TABLE ACCESS (FULL) OF 'EMPLOYEES' (TABLE) (Cost=4 Card=107 Bytes=749) 6 1 FILTER 7 6 SORT (JOIN) (Cost=5 Card=107 Bytes=1605) 8 7 TABLE ACCESS (FULL) OF 'EMPLOYEES' (TABLE) (Cost=4 C ard=107 Bytes=1605) 統計值---------------------------------------------------------- 351 recursive calls 0 db block gets 502 consistent gets 0 physical reads 0 redo size 1268 bytes sent via SQL*Net to client 449 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 50 sorts (memory) 0 sorts (disk) 38 rows processed 16:45:23 SQL> alter system flush shared_pool;已更改系統.16:45:45 SQL> select outer.last_name,outer.salary,outer.department_id16:45:45 2 from employees outer,(select department_id,avg(salary) avg_salary from employees groudepartment_id) inner16:45:45 3 where outer.department_id=inner.department_id16:45:45 4 and outer.salary>inner.avg_salary; --join连接查询已選取 38 個資料列. 執行計畫---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=11 Card=17 Bytes=6 97) 1 0 MERGE JOIN (Cost=11 Card=17 Bytes=697) 2 1 SORT (JOIN) (Cost=5 Card=11 Bytes=286) 3 2 VIEW (Cost=5 Card=11 Bytes=286) 4 3 HASH (GROUP BY) (Cost=5 Card=11 Bytes=77) 5 4 TABLE ACCESS (FULL) OF 'EMPLOYEES' (TABLE) (Cost=4 Card=107 Bytes=749) 6 1 FILTER 7 6 SORT (JOIN) (Cost=5 Card=107 Bytes=1605) 8 7 TABLE ACCESS (FULL) OF 'EMPLOYEES' (TABLE) (Cost=4 C ard=107 Bytes=1605) 統計值---------------------------------------------------------- 191 recursive calls 0 db block gets 257 consistent gets 0 physical reads 0 redo size 1268 bytes sent via SQL*Net to client 449 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 19 sorts (memory) 0 sorts (disk) 38 rows processed 16:45:46 SQL> JOIN连接查询比关联子查询性能上都有所提高。
     EXISTS/NO EXISTS操作符        -EXISTS运算符经常与相关的子查询一起使用,测试子查询检索的值的结果集中是否存在主查询检索的值。        -如果子查询返回至少一行,则该运算符返回TRUE。 如果该值不存在,则返回FALSE。         -NOT EXISTS测试主查询检索的值是否是子查询检索的值的结果集的一部分。       
 SELECT <column1>,<colum2>,...        FROM <table_name> outer        WHERE [EXISTS | NOT EXISTS] (SELECT <column1>,<column2>,....                                                            FROM <table_name>                                                            WHERE <column1> = outer.<column1>);
    关联UPDATE        
UPDATE <table_name> alias1            SET <column> = (SELECT expression                                        FROM <table_name> alias2                                         WHERE alias1.column = alias2.column);
        注意:关联UPDATE如果主查询选定值在子查询中未找到,SET栏位值将被更新成NULL值。        
     create table ORA_01407_T0(        id number not null,        name varchar2(10) not null        )        /        insert into ORA_01407_T0 values(1,'T01');        insert into ORA_01407_T0 values(2,'T02');        insert into ORA_01407_T0 values(3,'T03');        commit;         create table ORA_01407_T1(        id number not null,        name varchar2(10) not null        )        /        insert into ORA_01407_T1 values(3,'T1_T03');        insert into ORA_01407_T1 values(4,'T1_T04');         commit;         update ORA_01407_T0 a set a.name=(select name from ORA_01407_T1 b where a.id=b.id);                16:47:15 SQL> update ORA_01407_T0 a set a.name=(select name from ORA_01407_T1 b where a.id=b.id);        update ORA_01407_T0 a set a.name=(select name from ORA_01407_T1 b where a.id=b.id)                            *        ERROR 在行 1:        ORA-01407: 無法將 ("HR"."ORA_01407_T0"."NAME") 更新為 NULL         將NAME NOT NULL約束去掉        17:12:55 SQL> ALTER TABLE HR.ORA_01407_T0 MODIFY(NAME  NULL);        已更改表格.        17:12:58 SQL> update ORA_01407_T0 a set a.name=(select name from ORA_01407_T1 b where a        已更新 3 個資料列.        17:13:05 SQL> select * from ORA_01407_T0;            ID NAME        ---------- --------------------             1 ->可以看到關聯查詢中不匹配的記錄name欄被賦值為NULL。             2               3 T1_T03
解決方案:  使用MERGE函數進行處理,匹配記錄UPDATE   truncate table ORA_01407_T0;    ALTER TABLE HR.ORA_01407_T0 MODIFY(NAME  NOT NULL);    insert into ORA_01407_T0 values(1,'T01');    insert into ORA_01407_T0 values(2,'T02');    insert into ORA_01407_T0 values(3,'T03');    commit;     merge into ORA_01407_T0 a using ORA_01407_T1 b on (a.id=b.id)    when matched then update    set a.name=b.name      ;     17:20:34 SQL> merge into ORA_01407_T0 a using ORA_01407_T1 b on (a.id=b.id)    17:21:48   2  when matched then update    17:21:48   3  set a.name=b.name    17:21:48   4  ;    合併 1 個資料列.    17:21:49 SQL> select * from ORA_01407_T0;        ID NAME    ---------- --------------------         1 T01         2 T02         3 T1_T03

   关联DELETE

 10:51:14 SQL> select * from ora_01407_t0        10:51:41   2  ;             ID NAME        ---------- --------------------         1 T01         2 T02         3 T1_T0310:51:42 SQL> select * from ora_01407_t1;        ID NAME---------- --------------------         3 T1_T03         4 T1_T0410:51:46 SQL> delete10:53:05   210:53:07 SQL>10:53:07 SQL>10:53:07 SQL> delete from ora_01407_t0 t110:53:10   2  where id=(select id from ora_01407_t1 t210:53:10   3      where t2.id=t1.id);已刪除 1 個資料列.10:53:11 SQL> select * from ora_01407_t0;        ID NAME---------- --------------------         1 T01         2 T02
    WITH子句        -使用WITH子句可以将多个相同的SELECT语句块组成一个复杂的查询        -WITH子句 中查询块返回值会保存在用户默认的临时表空间        -使用WITH子句可提高性能                WITH子句好处            -查询语句块便于阅读            -减少解析,查询块多次出现只会评估一次            -多数情况下,可提高查询性能          例子:查询部门薪水大于部门平均薪水的部门        
col department_name format a20with  dept_costs as (    select d.department_name,sum(salary) as dept_total    from employees e join departments d    on e.department_id = d.department_id    group by d.department_name),  avg_cost as (      select sum(dept_total)/count(*) as dept_avg      from dept_costs)  select *  from dept_costs  where dept_total > (select dept_avg from avg_cost)  order by department_name;     DEPARTMENT_NAME      DEPT_TOTAL    -------------------- ----------    Sales                    304160    Shipping                 155950
    学习总结:            1.多行/多列子查询(成对/非成对比较)            2.关联子查询(主查询->子查询->返回值->主查询)和标量子查询(返回一个列值)、关联UPDATE/DELETE/SELECT            3.EXISTS和NOT EXISTS操作符            4.使用WITH子句 

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台