Oracle的SQL查詢總結
1 查詢語句
1.1獲取唯一記錄——distinct
獲取員工唯一工資狀況的SQL語句如下所示。
SQL> select distinct e.employee_name, s.salary
from employees e, salary s
where e.employee_id = s.employee_id;
1.2分組——group by子句
在數據庫查詢中,分組是一個非常重要的應用。分組是指將數據表中所有記錄中,以某個或者某些列爲標準,劃分爲一組。
進行分組查詢應該使用group by子句。group by子句指定分組標準,並將數據源按照該標準進行劃分,然後循環處理每組數據。
1.3 過濾分組——having子句
where子句可以過濾from子句所指定的數據源,但是對於group by子句所產生的分組無效。爲了將分組按照一定條件進行過濾,應該使用having子句。
爲了獲得工資總額大於10000的記錄,應該使用如下SQL語句。
select e.employee_id, e.employee_name, sum(s.salary) total_salary
from employees e, salary s
where e.employee_id = s.employee_id
group by e.employee_id, e.employee_name
having (sum(s.salary))>10000
1.4 排序——order by子句
order by子句用於排序結果集。order by子句在使用時需要指定排序標準和排序方式。排序標準是指按照結果集中哪個或哪些列進行排序;order by有兩種排序方式——升序(asc,同時也是默認排序方式)和降序(desc)。
對該搜尋結果按照工資水平由高到低的順序排列,SQL語句如下所示。
SQL> select distinct e.employee_name, s.salary
from employees e, salary s
where e.employee_id = s.employee_id
order by s.salary desc;
1.5 order by與group by子句
當兩種子句同時存在時,Oracle首先執行group by子句,然後才進行排序操作
order by子句所指定的排序列,必須出現在select表達式中。
獲得員工工資總額狀況,並按照工資總額由高到低的順序進行排列。
SQL> select e.employee_name, sum(s.salary) total_salary
from employees e, salary s
where e.employee_id = s.employee_id
group by e.employee_name
order by total_salary desc;
1.6 order by與distinct
order by子句與distinct關鍵字同時使用時,也必須遵循這樣一個規則——order by子句所指定的排序列,必須出現在select表達式中。
獲得所有員工姓名,並按工資進行升序排列。
SQL> select e.employee_name,s.salary
from employees e, salary s
where e.employee_id = s.employee_id
order by s.salary desc;
2 子查詢
子查詢是指在查詢語句的內部嵌入查詢,以獲得臨時的結果集。Oracle總是自動優化帶有子查詢的查詢語句。如果子查詢中的數
據源與父查詢中的數據可以實現連接操作,那麼將轉化爲連接操作;否則,將首先執行子查詢,然後執行父查詢。
2.1 查詢條件中的子查詢
例如,在表employees中存儲了員工信息。但是其中某些員工並未領取過工資。
那麼可以利用子查詢作爲查詢條件來獲得所有領取過工資的員工信息。
SQL> select * from employees
where employee_id in (select employee_id from salary);
2.2 建表語句中的子查詢
子查詢的另外一個應用場景用於建表語句中。
例如,Oralce的內置視圖user_objects描述了當前用戶所有對象信息。
現欲創建一個與該視圖具有相同結構的空數據表,則可以利用如下SQL語句。
SQL> create table tmp_user_objects
as select * from user_objects where 1<>1;
2.3 插入語句中的子查詢
我們也可以在插入語句中使用子查詢。這相當於向表中批量插入數據。
創建的數據表爲空表,我們可以利用子查詢向其中插入數據。
SQL> insert into tmp_user_objects
select * from user_objects
where object_type='TABLE';
select * from user_objects where object_type='TABLE'
用於獲得視圖user_objects中object_type爲“TABLE”的所有記錄。
該子查詢的所有記錄,將被插入表tmp_user_objects中。
3 聯合語句
聯合語句是指對於多個查詢所獲得結果集進行集合操作。
這些集合操作包括:union、union all、intersect和minus。
這些集合運算都是二元運算,運算結果仍然是一個記錄集合。
3.1 求並集(記錄唯一)——union運算
union運算實際是合併兩個結果集中的所有記錄,並將其中重複記錄剔除(保證結果集中的記錄唯一)。
實例:數據庫中存在着兩個表a_students和b_students,
分別存儲了參加了a培訓班和b培訓班的學生信息。
select student_id, student_name from a_students
union
select student_id, student_name from b_students;
3.2 求並集——union all運算
union all運算與union運算都可看做並集運算。
但是union all只是將兩個運算結果集進行簡單整合,並不剔除其中的重複數據。
這是與union運算的最大區別。
只需在上例union後加上all即可
3.3 求交集——intersect運算
interseect運算是指交集運算。
該運算可以獲得兩個結果集的交集——即同時存在於兩個結果集中的記錄。
在表a_students和表b_students中均存在着學生信息。
現欲獲得既參加了a班,又參加了b班的學生姓名。
即同時存在於兩個表中的學生姓名,則可以使用intersect運算。
相應的SQL語句如下所示。
SQL> select student_name from a_students
intersect
select student_name from b_students;
3.4 求差集——minus運算
minus是集合間的減法運算。該運算將返回第一個集合中存在,
而第二個集合中不存在的記錄。
現欲獲得參加了a培訓班,但是未參加b培訓的學生。
此時,我們可以利用minus運算獲得存在於表a_students中,
而不存在於表b_students中的學生姓名。
SQL> select student_name from a_students
minus
select student_name from b_students;
3.5 聯合語句的混合運算
對於這四種集合運算——union運算、uion all運算、intersect運算和minus運算,
Oracle允許進行混合運算。在混合運算時,這四種運算的優先級是相同的,
也就是說,他們將按照自左至右的順序依次進行。
intersect和union all的混合運算。
SQL> select student_name from a_students
intersect
select student_name from a_students
union all
select student_name from b_students
4 連接
在大多數查詢中,所使用的數據源往往有多個。
當多個數據源同時使用時,這些數據源如何進行組合便成爲了一個至關重要的問題。連接即用來指定多個數據源之間的組合關係。默認情況下,多個數據源之間使用的是笛卡爾積方式進行組合。除此之外,Oracle還提供了另外幾種特殊的組合方式。這些特殊方式有效補充了笛卡爾積的不足
4.1 自然連接
自然連接,顧名思義,即無需用戶指定任何連接條件,只需指定連接的兩個數據源。至於兩個數據源如何進行數據整合則無需用戶操心。
自然連接所使用的關鍵字爲natural join。其連接原則爲,兩個數據源的共有列,並且具有相同列值。
表employees和表salary都包含了employee_id列。
二者可以進行自然連接操作,相應的SQL語句如下所示。
select * from employees natural join salary;
natural join用於兩個表之間的自然連接。
搜尋結果獲得的結果集,將含有公共列employee_id。
這裏所說的公共列是指,不能爲列employee_id指定限定詞。
例如,不能將列employee_id標識爲特定表employees或者salary中的列。
SQL> select e.employee_id
4.2 內連接
自然連接強制使用兩個表之間的公共列作爲搜尋條件;而且要求公共列的值必須相等。這帶來了極大的限制,
因此,自然連接並不常用。而內連接突破了這兩種約束。
內連接可以自行指定連接列和連接條件。內連接運算的關鍵字爲inner join。
同樣爲了實現獲得員工工資狀況這一需求,利用內連接的SQL語句如下所示。
SQL> select e.employee_id, e.employee_name, s.month, s.salary
from employees e
inner join salary s
on e.employee_id = s.employee_id;
4.3 外連接
內連接所指定的兩個數據源,處於平等的地位。而外連接不同,外連接總是以一個數據源爲基礎,將另外一個數據源與之進行條件匹配。即使條件不匹配,基礎數據源中的數據總是出現在結果集中。那麼,依據哪個數據源作爲基礎數據源,便出現了兩種外連接的方式——左(外)連接和右(外)連接。因爲內連接沒有左右之分,所以習慣上,我們將左外連接和右外連接簡稱爲左連接和右連接。
1.左連接
2. 右連接
3. 外連接的簡略寫法
簡略寫法的優劣
5.完全連接
語句片斷:
SELECT MODELNAME, TABLENAME
FORM EMCD_MONITOR_MODEL , EMCD_MONITOR_TABLE
WHERE EMCD_MONITOR_TABLE.MODELID(+) =EMCD_MONITOR_MODEL.ID
此SQL文使用了右連接,即“(+)”所在位置的另一側爲連接的方向,右連接說明等號右側的所有記錄均會被顯示,無論其在左側是否得到匹配,如果沒有匹配則顯示爲空;
始終記住(+)所在位置的另一側爲連接的方向,如A.bid(+)=B.id,即以該方向的B表作爲根,掃描B表以驅動A的掃描匹配;顯示的時候B的所有信息均顯示,對應的另一側A的記錄有則顯示,沒有則空着。
反之, A.bid=B.id (+)爲左連接;
相當於標準SQL裏面的left/right outer join
5 層次化查詢
關係型數據庫中,同一個數據表中的記錄具有相同的列,因此,
不同的記錄之間存在着平行關係。但是,有時候,各記錄之間也
可能存在着“父子”關係。當這些“父子”關係較爲複雜時,我們可以
將整個表中的數據看做樹狀結構,而基於樹狀結構數據的查詢,
稱爲層次化查詢。
5.1 樹狀模型
樹狀模型一個很典型的實例爲市場信息。不同層級的市場之間存在着父子關係。
5.2 層次化查詢
自9i版本開始,Oracle提供了層次化查詢方案來遞歸獲得樹狀模型的信息。層次化查詢的語法如下所示。
select 列名1、列名2...
from 表名
start with 開始條件
connect by 遞歸條件
其中,start with指定查詢的起點,即從哪些記錄開始進行查詢;connect by指定遞歸條件,如果獲得下一條記錄。
5.3 層次化查詢的相關函數
對於層次化查詢,最常用的函數爲sys_connect_by_path()函數。層次化查詢總是以某條記錄爲起點,根據connect by所指定的條件遞歸獲得結果集合。而sys_connect_by_path()函數,則可以對起始至當前記錄之間的結果集進行聚合操作。該操作僅限於串聯字符串,相應的語法如下所示。
sys_connect_by_path(列名,分隔符)
其中,列名指定將哪個列的值進行串聯,而分隔符則指定字符串串聯時的分隔符。