【數據庫】Oracle中的複雜數據處理

在介紹了Oracle中的基本數據類型及相應的處理函數後,本章將介紹Oracle中較爲複雜的數據處理。

接下來,本文將介紹:

1、利用聚合函數來統計數據;

2、常用技巧;

3、oracle中的基本運算;

4、oracle特殊判式;

5、oracle中的分析與窗口函數


1. 利用聚合函數統計數據

前面幾篇博客介紹的,都有一個共同的特點:均針對單一數據。

而聚合函數則是針對多個數據獲得統計結果。使用聚合函數的場景大多爲表中的數據,接下來的所有示例均基於表employees,其數據結構及內容如下所示。

SQL>select * from employees


表employees中存儲了員工的基本信息,有員工ID、員工姓名、員工職位、員工年齡、員工家庭住址。


1.1 求最大值----max()函數

max()函數可以用於獲得一組數據中的最大值,這裏的“一組數據”通常爲表中某列的所有值,max()函數可以應用的數據類型包括數值型和字符型。

(1)max()函數應用於數值型

max()函數應用於數值型時,是按照數值的大小順序來獲得最大值。

例子:爲了獲得員工的最大年齡可以利用如下所示的SQL語句

SQL>select max(employee_age) max_age from employees;

------

37

from employees提供了表employees中的所有記錄作爲數據源;max(employee_age)中的employee_age爲數據列,該列的所有數據組成了max()函數的參數,max()函數則統計該組數據中的最大值。

max()函數的返回值是一個統計值,與數據表中的元數據並沒有一一對應的關係。例如:表employees中可能存儲了多個37歲的員工信息,而max()函數的返回值只是一個統計值。


(2)max()函數應用於字符型

max()函數不僅可以應用於數值型,還可以應用於字符型。當應用於字符型時,oracle會依照字母表由前到後的順序進行排序。

例子:在表employees中,列employee_name爲字符型,可以利用max()函數來獲得去最大值。

SQL>select max(employee_name ) max_name from employees;

--------

鍾小平


(3)max()函數應用於日期型

日期型的實質也是數值型,因此,max()函數應用於日期型與數值型具有完全相同的效果-----獲得最晚日期。


1.2 求最小值-----min()函數

與max()函數相反,min()函數可以獲得最小值。min()函數同樣可應用於數值型、字符型和日期型。


1.3 求平均值-----avg()函數

avg()函數用於獲得一組數據的平均值,該函數只能應用於數值型。

avg()函數的返回值是一個number型。


1.4求和----sum()函數

sum()函數用於獲得一組數據的和。該函數同樣只能應用於數值型。

例子:爲了獲得employees中所有員工年齡之和,可以利用如下SQL語句。

SQL.>select sum(employee_age ) sum_age from employees;


1.5 統計記錄數-----count()函數

count()函數用於統計記錄數目。該函數的常見使用場景有3種。

(1)統計單列

對於統計單列來說,列名作爲count()函數的參數,當列值不爲空時,將計數1;否則,將計數0。


(2)統計所有列

當表的所有列被作爲count()函數的參數,即count(*)進行統計時,即使所有列值均爲空,oracle仍將進行計數。

select count(*) from employees;


(3)利用count(1)進行統計

對於count()函數來說,還可以利用count(1)的形式進行統計。count(1)與count(*)返回的值相同,對每條記錄都計數1.

SQL>select count(1) from employee;


2、oracle中的常用技巧

除了針對基本數據類型的各種函數之外,oracle還提供了一些其他技巧性函數。比如:

多值判斷---decode()函數、爲空值重新賦值---nvl()函數、結果集的行號----rownum()函數、強制轉換數據類型-----cast()函數

2.1 多值判斷-----decode()函數

在oracle中,可以利用if else和case語句進行判斷,當然還有decode()函數處理該問題,從而減少了代碼量,並增強了SQL語句的可讀性。

decode()函數的使用語法如下:

decode(表達式,比較值1,結果值1,比較值2,結果值2,....,默認值)

decode()函數的處理過程類似於解碼過程,第一個參數表達式往往爲變量或者數據表中的列;其後的參數總是以“比較值---結果值”對的形式出現,表達式的值與“比較值”進行比較,如果二者相等,則返回相應的“結果值”;若果所有比較都不成功,那麼將返回默認值。

例子:在表employees所存儲的數據表中,列employee_position標識了員工的職位,現需要對員工進行分類:職位是工程師的員工規劃技術部,其他員工劃爲行政管理部。那麼可以利用decode()函數來實現這一用法。


decode(sign(instr(employee_position,'工程師')), 1, '技術部', '行政管理部')中 sign(instr(employee_position,'工程師'))用於獲得列employee_position中字符串“工程師”的位置,並判斷其正負性;1,‘技術部’是第一個“比較值---結果值”鍵值對,表示當員工爲工程師時,返回字符串“技術部”;最後一個參數“行政管理部”爲默認值。


2.2 空值處理-----nvl()函數

數據庫中的數據難免出現空值,但是對於用戶來說,空值並不夠友好。用戶更願意獲得有意義的數據,nvl()函數可以判斷表達式的值是否爲空。如果爲空,則可以返回新值;若不爲空,則返回原值。其使用語法如下所示:

nvl(表達式,新值/表達式)

nvl()函數首先判斷第一個表達式參數的值是否爲空;如果爲空,則返回第二個參數的的值;如果不爲空,則返回第一個參數表達式的值。

例子:表employees和表salary分別存儲了員工及員工工資信息,可以通過分組獲得員工及員工總額信息。

nvl(sum(salary), 0 ) 用於判斷員工的工資總額是否爲空,如果爲空則返回0,因此記錄1--5的工資總額仍然保持原值,而記錄6--8的工資總額被置爲0.


2.3 結果集的行號----rownum()函數

rownum()函數可以返回結果集的行號,對於select語句,沒捕獲一條記錄,rownum()函數的返回值將累加1,否則,rownum()的返回值保持不變。

(1)利用rownum爲搜尋結果添加一列

例子:rownum的最簡單應用場景是爲搜尋結果添加一列,如下所示。

SQL>select e.employee_id,  e.employee_name, rownum from emplyees e;

select e.employee_id,  e.employee_name, rownum from emplyees e用於遍歷表employees,並捕獲每條記錄中的employee_id和employee_name列;每捕獲一條記錄,rownum的返回值將累加1,因此,rownum依次返回1--8的值。


(2)rownum與order by子句。

對錶中數據排序,然後獲得排名在某個範圍之內的記錄是一種常見需求。例如,要求獲得表employees中、按員工姓名排序前3位的員工信息。一種常見的思路爲綜合利用rownum與order by子句排序並增加過濾條件----rownum小於等於3.

SQL>select e.employee_id, employee_name, rownum from employees e where rownum <= 3 order by e.employee_name;

EMPLOYEE_ID    EMPLOYEE_NAME    ROWNUM

-------------------       -------------------------     -----------

3                                  劉俊                               3 

1                                  王曉                              1

2                                   鍾小平                          2

where rownum<=3用於限制rownum小於等於3的記錄;order by e.employee_name用於對錶employees中的記錄按照employee_name列進行排序。

從上面的查詢結果可以看出,並不是預期的效果。原因在於where條件先於order by子句執行。也就是說,Oracle總是先利用where條件過濾搜尋記錄,最後才利用order by進行排序。而rownum的返回值用於where條件判斷,這造成了所有rownum執行完畢之後在再執行排序操作。

該需求的正確解決方式爲,首先利用內嵌式圖獲得排序之後的結果,然後對內嵌視圖所代表的結果集使用rownum()函數,SQL語句如下所示:

SQL>select t.*, rownum from (

select e.employee_id, employee_name from employees e order by e.employee_name)  t where rownum<=3

EMPLOYEE_ID   EMPLOYEE_NAME     ROWNUM

--------------------    -------------------------     ---------------

7                                 李四                                 1

3                                 劉俊                                  2

4                                  王龍                                 3

內嵌視圖 t  的定義爲select e.employee_id, employee_name from employees e order by e.employee_name.該內嵌視圖所代表的結果集如下:

EMPLOYEE_ID                EMPLOYEE_NAME

---------------------                ---------------------------

7                                                   李四

3                                                    劉俊

4                                                   王龍

8                                                    王五

1                                                    王曉

6                                                    張三

5                                                    鍾文

2                                                    鍾小平

對該結果集來說,rownum<=3將返回前3條記錄,即爲:

EMPLOYEE_ID           EMPLOYEE_NAME

-------------------             ----------------------------

7                                        李四

3                                        劉俊

4                                        王龍

因此,對於rownum()函數的使用來說,首先要觀察rownum()函數出現在查詢語句的哪個子句中,而子句的執行時機往往決定rownum()函數的返回值。


(3)rownum與比較運算符“=‘

rownum()函數常常出現在查詢條件中,SO,rownum()函數與比較運算符“=”的結合使用。

例子:現需要獲得employees中,行號爲1的員工信息,最容易想到的SQL語句如下:

SQL>select e.employee_id, e.employee_name, rownum from employees e where rownum =1;

分析查詢結果可知,利用rownum=1可以獲得預期的結果,但是,利用該方法無法成功獲得行號爲4的員工信息。

【分析】這是因爲rownum總是從1開始,如果不能獲得rownum爲1的記錄,那麼rownum的返回值永遠無法達到大於1的數字。可以通過分析該SQL語句的執行過程解釋查詢失敗的原因。

select e.employee_id, e.employee_name, rownum from employees e 用於自表employees中獲取記錄;where rownum=4則指定了過濾條件;當Oracle遍歷至表employees的第一條記錄時,rownum爲1,但是where rownum=4爲假,那麼該記錄不在捕獲範圍;當遍歷至表employees的第二條記錄時,因爲捕獲記錄爲0,rownum仍然返回 1,;以此類推,無論Oracle遍歷多少條記錄,rownum總是爲1,也永遠無法滿足rownum=4的條件。

事實上,單純利用rownum=n作爲查詢語句的過濾條件,當n大於1室,返回的查詢結果永遠爲空。此處,仍然可以通過內嵌視圖來解決該問題。


(4)rownum與比較運算符“>”

例子:與比較運算符“=”類似,如果對rownum使用了對於運算,而比較值又大於等於 1 時,Oracle同樣返回空的結果集。

如果,當rownum>n中的  n 小於1,那麼查詢語句將返回所有記錄。


2.4 強制轉換數據類型-----cast()函數

Oracle中的cast()函數可以強制轉換列或變量的數據類型。其語法如下所示:

cast( 元數據  as   新的數據類型 )


3、Oracle中的運算

Oracle中的常用運算包括數學運算、邏輯運算、比較運算和按位運算。


4、Oracle中的特殊判式

Oracle進行條件判斷時,最常見的操作符爲“=’。除此之外,oracle還提供了若干特殊判式進行邏輯判斷。這些判式包括:

between-----範圍測試;in-----集合成員測試;like----模糊匹配;is null-----空值判斷;exits-----存在性判斷;all、some、any----數量判斷。

4.1 between-----範圍測試

between可以用於判斷列或表達式的值是否處於某個範圍之內。其使用語法如下:

between x and y

其中,x和y限定了範圍的臨界值。


4.2 in -------集合成員測試

in判式用於判斷某個列或表達式的值是否處於某個結合之內


4.3 like-----模糊匹配

用戶在查詢數據時,往往並不能提供精確的匹配條件。例如:用戶試圖通過公司名稱查詢記錄時,並不能提供精確的公司全稱;又如,用戶可能希望獲得某位員工的信息,而只能確定員工的姓氏。這些情況下,即可使用模糊查詢,oracle中提供了like判式實現模糊匹配。

(1)、匹配任意字符串----“%”

對於like判式,最常用的通配符爲“%”,該通配符可用於匹配任意長度的任意字符。

比如:'劉%',指定查詢條件爲該列的值以“劉”爲開頭,後面跟任意長度的任意字符,因此將返回所有劉姓員工的姓名。


(2)、匹配單個字符-----“_”

對於like判式,另外一個常用通配符爲“_”。該通配符可用於匹配任意的單個字符。

例子:'劉_',指的是劉後面只能跟一個字符。。

當然,多個通配符“_”可以同時使用,比如:'劉__',劉後面跟着兩個“_”。


(3)原義字符

在like判式中,通配符“%”和“_” 有着特殊的意義。但是有時候用戶希望判斷標準中出現了這兩個字符,那麼將需要二者的原義字符。

例子:對於一個字符串,百分比“20%”,用戶希望判斷是否該字符串以“%”結尾,直接在判式中使用“%”無法達到預期效果。

因此,需要用到"\";   like ‘%\%’中的第一個%,表示通配符;而後面的表示原義字符。  


4.4 is null  -----空值判斷

oracle中不能使用“=”判斷一個列或者表達式的值是否爲空 ,而是利用特殊判式 is null.

當然,is null判式的對立面是is not null,爲了獲得所有列值均完整無缺的記錄,相應的SQL語句如下所示。

SQL> select * from employees 

where employee_id is not null

and employee_name in not null

and ....

............

利用is not null對錶中的所有列進行判斷,可以獲得所有列值均不爲空的記錄。


4.5 exits---存在性判斷

exits判式可以用於判斷記錄的存在性,exits判式的操作對象是結果集,當結果集匯中記錄大於0時,將返回爲真,否則,將返回爲假。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章