Oracle 在連線條件裡處理和比較 NULL 值
當進行表連線時,希望把 NULL 值對映到一個預設值上,這樣就可以避免使用外連線了。可以用 NVL 函式把待連線表的外來鍵列上的 NULL 值進行轉換。
SQL> select employee_id, first_name, last_name, department_id
2 from hr.employees
3 where employee_id = 178;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID
----------- -------------------- ------------------------- -------------
178 Kimberely Grant
使用外連線的方式處理
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 left join hr.departments d
4 on e.department_id = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
112 Jose Manuel Urman 100 Finance
111 Ismael Sciarra 100 Finance
110 John Chen 100 Finance
109 Daniel Faviet 100 Finance
108 Nancy Greenberg 100 Finance
206 William Gietz 110 Accounting
205 Shelley Higgins 110 Accounting
178 Kimberely Grant
以下查詢把所有部門為 NULL 的 EMPLOYEE 轉換到編碼位 110 的部門
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
109 Daniel Faviet 100 Finance
110 John Chen 100 Finance
111 Ismael Sciarra 100 Finance
112 Jose Manuel Urman 100 Finance
113 Luis Popp 100 Finance
178 Kimberely Grant 110 Accounting
205 Shelley Higgins 110 Accounting
206 William Gietz 110 Accounting
在條件連線中,把 NULL 對映到非 NULL 值來避免使用 OUTER JOIN 可能會存在效能方面的問題,因為不會用到 EMPLOYEES.DEPARTMENT_ID 上的索引(主要是因為 NULL 列沒有索引)。我們可以用基於函式的索引來解決這個問題。
建立索引前的執行計劃
SQL> explain plan for select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1343509718
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 4028 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 106 | 4028 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 27 | 432 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 107 | 2354 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2354 | 3 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
filter("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
建立索引
SQL> create index hr.employees_dpet_fbi on hr.employees(nvl(department_id,110));
索引已建立。
建立索引後的執行計劃
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2904398956
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 5136 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 107 | 5136 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS | 27 | 432 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 4 | 128 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMPLOYEES_DPET_FBI | 4 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access(NVL("DEPARTMENT_ID",110)="D"."DEPARTMENT_ID")
已選擇16行。
SQL> select employee_id, first_name, last_name, department_id
2 from hr.employees
3 where employee_id = 178;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID
----------- -------------------- ------------------------- -------------
178 Kimberely Grant
使用外連線的方式處理
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 left join hr.departments d
4 on e.department_id = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
112 Jose Manuel Urman 100 Finance
111 Ismael Sciarra 100 Finance
110 John Chen 100 Finance
109 Daniel Faviet 100 Finance
108 Nancy Greenberg 100 Finance
206 William Gietz 110 Accounting
205 Shelley Higgins 110 Accounting
178 Kimberely Grant
以下查詢把所有部門為 NULL 的 EMPLOYEE 轉換到編碼位 110 的部門
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
109 Daniel Faviet 100 Finance
110 John Chen 100 Finance
111 Ismael Sciarra 100 Finance
112 Jose Manuel Urman 100 Finance
113 Luis Popp 100 Finance
178 Kimberely Grant 110 Accounting
205 Shelley Higgins 110 Accounting
206 William Gietz 110 Accounting
在條件連線中,把 NULL 對映到非 NULL 值來避免使用 OUTER JOIN 可能會存在效能方面的問題,因為不會用到 EMPLOYEES.DEPARTMENT_ID 上的索引(主要是因為 NULL 列沒有索引)。我們可以用基於函式的索引來解決這個問題。
建立索引前的執行計劃
SQL> explain plan for select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1343509718
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 4028 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 106 | 4028 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 27 | 432 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 107 | 2354 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2354 | 3 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
filter("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
建立索引
SQL> create index hr.employees_dpet_fbi on hr.employees(nvl(department_id,110));
索引已建立。
建立索引後的執行計劃
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2904398956
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 5136 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 107 | 5136 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS | 27 | 432 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 4 | 128 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMPLOYEES_DPET_FBI | 4 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access(NVL("DEPARTMENT_ID",110)="D"."DEPARTMENT_ID")
已選擇16行。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26506993/viewspace-2018523/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- FastJson 序列化處理 null 值ASTJSONNull
- 關於外連線和where條件
- 【NULL】Oracle null值介紹NullOracle
- 檢視oracle資料庫中,哪些表的欄位是null值比較多Oracle資料庫Null
- Oracle date 型別比較和String比較Oracle型別
- 【C#】-對於Null值的處理方法C#Null
- 麒麟659和麒麟710處理器引數比較
- Oracle OCP(02):條件和排序Oracle排序
- doxygen 宏定義/宏編譯/條件編譯/預處理/預編譯 不處理、忽略條件、分析所有條件、滿足所有條件的方法編譯
- oracle高水位線處理Oracle
- Mysql關於長連線短連線優劣比較MySql
- Effective c++條款11:在operator=中處理“自我賦值”C++賦值
- AutoMapper如何全域性配置map條件過濾null值空值對所有對映起效APPNull
- 華為麒麟659和麒麟710處理器引數比較
- java檔案複製方式在100MB檔案條件下速度的比較Java
- NULL在oracle和mysql索引上的區別NullOracleMySql索引
- T-SQL——關於Join on的的連線條件和where的篩選條件的區分SQL
- PHP7 ?? 與 ?: 的作用和區別(null合併運算子, null條件運算子)PHPNull
- MATLAB一維插值和二維插值 比較Matlab
- 04 Windows批處理中的條件執行Windows
- [20180319]windows批處理檔案大小比較.txtWindows
- 在不允許新建物件的條件下,將list中指定條件的值去除物件
- 關聯查詢完,寫個 select 把條件放在外面,方便條件處理
- tomcat連線處理機制和執行緒模型Tomcat執行緒模型
- Oracle與PostgreSQL比較:PostgreSQL至少在安裝和大小方面擊敗了Oracle - foersterOracleSQL
- 比較檔案是否相同,(比較MD5值)
- PbootCMS整理判斷是否連結賦值各種條件判斷和標籤boot賦值
- 介面自動化的前置條件怎麼處理
- js 深比較和淺比較JS
- postgresql連線失敗如何處理SQL
- 行連線的處理方式指引
- windows 處理bat連線本地mysqlWindowsBATMySql
- Oracle OCP(06):通用函式和條件表示式Oracle函式
- 瑞芯微RK3399和RK3399Pro處理器效能比較
- Oracle審計--AUD$佔用空間較大處理方案Oracle
- [Python影象處理] 七.影象閾值化處理及演算法對比Python演算法
- ABAP OPEN SQL裡OPEN CURSOR和SELECT的比較SQL
- OPUS裡的Silk和原始Silk簡單比較
- oracle中的條件語句Oracle