(Les17 Retrieving Data Using Subqueries)[20180103]

来源:https://www.cnblogs.com/also-brook/archive/2018/01/05/8203410.html
-Advertisement-
Play Games

學習目標: -多列子查詢 -SQL語句中使用標量子查詢 -更新或刪除行使用關聯子查詢 -使用EXISTS和NOT EXISTS操作符 -使用WITH子句 多列子查詢 語法: Main query WHERE (<column_name>,<column_name>) IN Subquery; 列的比 ...


學習目標:     -多列子查詢     -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 a30 16:32:16 SQL> set pagesize 1200 16:32:16 SQL> select last_name,salary,department_id 16:32:16 2 from employees outer 16:32:16 3 where salary >(select avg(salary) 16:32:16 4 from employees 16:32:16 5 where department_id=outer.department_id) 16:32:16 6 ; LAST_NAME SALARY DEPARTMENT_ID ------------------------------ ---------- ------------- Hartstein 12990 20 Raphaely 10990 30 Weiss 7990 50 Fripp 8190 50 Kaufling 7890 50 Vollman 6490 50 Mourgos 5790 50 Ladwig 3590 50 Rajs 3490 50 Sarchand 4190 50 Bull 4090 50 Chung 3790 50 Dilly 3590 50 Bell 3990 50 Everett 3890 50
語句改寫:
col last_name format a30
set pagesize 1200 select last_name,salary,department_id from employees outer where salary >(select avg(salary) from employees where department_id=outer.department_id) minus select outer.last_name,outer.salary,outer.department_id from employees outer,(select department_id,avg(salary) avg_salary from employees group by department_id) inner where outer.department_id=inner.department_id and outer.salary>inner.avg_salary; 對比兩種寫法: 16:45:11 SQL> set autotrace traceonly 16:45:21 SQL> alter system flush shared_pool; 已更改系統. 16:45:22 SQL> select last_name,salary,department_id 16:45:22 2 from employees outer 16:45:22 3 where salary >(select avg(salary) 16:45:22 4 from employees 16: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_id 16:45:45 2 from employees outer,(select department_id,avg(salary) avg_salary from employees grou department_id) inner 16:45:45 3 where outer.department_id=inner.department_id 16: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_T03
10:51:42 SQL> select * from ora_01407_t1;
        ID NAME
---------- --------------------
         3 T1_T03
         4 T1_T04
10:51:46 SQL> delete
10:53:05   2
10:53:07 SQL>
10:53:07 SQL>
10:53:07 SQL> delete from ora_01407_t0 t1
10:53:10   2  where id=(select id from ora_01407_t1 t2
10: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 a20
with
  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子句  
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 學習目標 -理解分層查詢概念 -創建樹形組織報告 -格式化分層數據 -樹形組織排除分支 分層查詢 語法 SELECT [LEVEL],<column>,exper ... FROM <table_name> [WHERE condition(s)] START WITH condition(s) C ...
  • 操作系統 : CentOS7.3.1611_x64 go語言版本:1.8.3 linux/amd64 InfluxDB版本:1.1.0 源碼路徑: github.com/influxdata/influxdb/cmd/influxd 程式入口(main.go): 在main函數中,調用Main.Ru ...
  • 1. 優先安裝軟體1. net framework3.5。2. 在安裝SQL SERVER 2012前需要3.5的支持。在WIN 2012系統可以在系統管理的添加角色和功能中安裝,如下將【.NET Framework 3.5功能】、【.NET Framework 4.5功能】下的組件全部勾選上。3.... ...
  • Sqoop是一個用來將Hadoop和關係型資料庫中的數據相互轉移的工具,可以將一個關係型資料庫(例如 : MySQL ,Oracle ,Postgres等)中的數據導進到Hadoop的HDFS中,也可以將HDFS的數據導進到關係型資料庫中。Sqoop是為大數據集設計的。Sqoop支持增量更新,將新記 ...
  • SQL Server授權購買簡單介紹 之前有同事問我,使用盜版序列號的SQL Server到底有沒有性能限制,之前本人一直沒有深入研究過,後來經過一番資料搜集和查證,彙總成這篇文章 微軟的SQL Server產品分為兩種賣法 1、盒裝 1、盒裝 :Server+CAL授權方式(SQL2017取消了S ...
  • 概念對比介紹 相信有些人會對ORACLE當中的AMM(Automatic Memory Management)與ASMM(Automatic Shared Memory Management)有些迷惑或混淆,不清楚兩者的異同,本文會從幾個方面來總結一下兩者的異同。如有不足或疏漏之處,敬請指正! 從O... ...
  • Liquibase是一個用於跟蹤、管理和應用資料庫變化的開源的資料庫重構工具。它將所有資料庫的變化(包括結構和數據)都保存在XML文件中,便於版本控制。 Liquibase具備如下特性:* 不依賴於特定的資料庫,目前支持包括Oracle/Sql Server/DB2/MySql/Sybase/Pos ...
  • 通過phpmyadmin登陸時提示以下錯誤: phpmyadmin crypt_random_string requires at least one symmetric cipher be loaded 報錯原因:路徑問題。 解決辦法: 1、進入到phpmyadmin根目錄下,打開\librari ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...