SQL语言之多表查询(oracle)
多表查詢
當查詢的數據并不是來源一個表時,需要使用多表連接操作完成查詢。根據不同表中的 數據之間的關系查詢相關聯的數據。
一、笛卡爾乘積(Cartesian product)
在數學中,兩個集合x和y的笛卡爾積,又稱直積,表示x*y,第一個對象是x的成員 而第二個對象是y的所有可能有序對的其中一個成員。
?如果避免出現笛卡爾乘積
當一個連接條件無效或被遺漏時,其結果是一個笛卡爾乘積,其中所有的行組合都 被顯示。第一個表中的所有行連接到第二個表中的所有行。一個笛卡爾乘積會產生 大量的行,其結果為無用結果。應該在where子句中始終包含一個有效的連接條 件;
(以hr用戶中的employees、departments表為例)
例
笛卡爾乘積效果
Select * from employees,departments;
二、多表連接語法(SQL86版)
?語法結構
使用一個連接查詢多個表的數據;
?在where子句中寫連接條件;
?當有多個表中有相同的列名時,將表明或者表的別名作為列名的前綴;
?定義連接
當數據庫從多表中查詢是,要使用連接(join)條件,一個表中的行按照存在相應 列中的值被連接到另一個表中的行;
?原則
?在寫一個連接表的select語句時,在列名前用表明或者表別名可以使語義清楚,并且加快數據庫訪問;
?為了連接n個表在一起,至少需要n-1個連接條件。例:為了連接4個表,至少需要3個連接條件。
三、等值連接
也稱為簡單連接(simple joins)或內連接(inner joins)。是通過等號來判斷連接條件中 的數據值是否匹配;
?抉擇矩陣(decision matrix)
通過行與列來分析一個查詢的方式;
(以hr用戶中的employees、departments表為例)
例
顯示同一個部門中所有名字為Taylor的雇員的名字和部門名稱,可以寫出下面的 抉擇矩陣:(以hr用戶中的employees、departments表為例)
例
查詢所有雇員名字以及他們所在的部門名稱;Select last_name,department_name from employees,departments where employees.department_id = departments.department_id;?使用and操作符附加搜索條件
除了連接以外,還可以要求where子句在連接中限制一個或多個表中的行; (以hr用戶中的employees、departments表為例)例
顯示同一個部門中所有名字為Taylor的雇員的名字和部門名稱;Select last_name ,department_name from employees , departments where last_name = ‘Taylor’ and employees.department_id = departments.department_id;?使用表別名
用于簡化語句的長度;
?表別名:代替表名,跟列別名相同;有助于保持SQL代碼較小,從而使用的存儲器也較少;
?原則
1.表別名最多可以有30個字符,但短一些更好;
2.如果在from子句中表別名被用于指定的表,那么整個select語句中都可 以使用表別名;
3.表別名應該有意義;
4.表別名只對當前select語句有效;
(以hr用戶中的employees、departments表為例)
例
使用表別名方式改寫顯示同一個部門中所有名字為 Taylor 的雇員的名字和部門名 稱; Select last_name , department_name from employees em , departments de where last_name = ‘Taylor’ and em.department_id = de.department_id;
?多于兩個表的連接
為了連接n個表,你最少需要n-1個連接條件。例:為了連接3個表,最少需要兩 個連接;
(以hr用戶中的employees、departments、locations表為例)
例
一、查詢每個雇員的名字、崗位名稱和工作地點;Select last_name , department_name , city from employees em , departments de , locations lo where em.department_id = de.department_id and de.location_id = lo.location_id; 二、查詢Taylor的雇員ID、部門名稱和工作城市;Select last_name , employee_id , department_name , city from employees em , departments de , locations lo where last_name = ‘Taylor’ and em.department_id = de.department_id and de.location_id = lo.location_id;四、非等值連接
一種不使用相等(=)作為連接條件的查詢。如:!=、>、<、>=、<=、between and等都是非等連接的條件判斷;
(以hr用戶中的employees、job_grades表為例)
例
查詢所有雇員的薪水級別; Select em.last_name , em.salary , gr.gra from employees em , jog_grades gr where em.salary between gr.lowest and gr.high;五、自連接
使用一個表連接他自身的操作;
(以hr用戶中的employees為例)
例
查詢每個雇員的經理的名字以及雇員的名字; select worker.last_name,manager.last_name from employees worker, employees manager where worker.manager_id=manager.employee_id;六、外連接
查詢出符合連接條件的數據的同時還包含孤兒數據。左外連接包含左表的孤兒數據, 右外連接包含右表的孤兒數據,全外連接包含兩個表中的孤兒數據;?孤兒數據(orphan data)
被連接的列的值為空的數據;
?外連接類型(SQL99)
?左外(left outer join):包含左表的孤兒數據。
?右外(right outer join):包含右表的孤兒數據;
?全外(full outer join):包含倆個表中的孤兒數據;
?SQL中的外連接
?語法格式
用left outer join | right outer join | full outer join定義連接類型,用on()子句 創建連接條件;
?左外連接(left outer join)
(以hr用戶中的employees、departments表為例)
例
查詢雇員的名字以及他們所有的部門名稱,包含那些沒有部門的員工;Select em.last_name,de.department_name from employees em left outer join departments de on( em.department_id = de.department_id);?右外連接(right outer join)
(以hr用戶中的employees、departments表為例)
例
查詢雇員的名字以及他們所有的部門名稱,包含那些沒有員工的部門;Select em.last_name, de.department_name from employees em right outer join departments de on( em.department_id = de.department_id);?全連接(full outer join)
(以hr用戶中的employees、departments表為例)
例
查詢雇員的名字以及他們所有的部門名稱,包含那些沒有部門的員工和沒有員工的部門;Select em.last_name, de.department_name from employees em full outer join departments de on( em.department_id = de.department_id);?Oracle擴展的外連接
通過在連接條件的后側使用(+)來表示是否顯示孤兒數據,有(+)表示不顯示孤 兒數據而另一側顯示孤兒數據。但這種寫法僅能在Oracle數據庫中使用;
(以hr用戶中的employees、departments表為例)
例
查詢雇員的名字以及他們所有的部門名稱,包含那些沒有部門的員工; select em.last_name,de.department_name from employees em ,departments de where em.department_id=de.department_id(+);(以hr用戶中的employees、departments表為例)
例
查詢雇員的名字以及他們所有的部門名稱,包含那些沒有員工的部門;Select em.last_name,de.department_name from employees em,departments de where em.department_id(+) = de.department_id;?SQL99中的交叉連接(用處不大,產生笛卡爾乘積)
?Cross join子句導致兩個表的交叉乘積;
?該連接和連個表之間的笛卡爾乘積是一樣的;
(以hr用戶中的employees、departments表為例)
例
查詢 Employees 表與 Departments 表的笛卡爾乘積。Select * from employees cross join departments;?SQL99中的自然連接(natural join)(不建議使用)
?相當于等式連接的另一種寫法,簡化了等式連接的寫法,性能相同;
?Natural join子句基于兩個表之間有相同名字的所有列;
?從兩個表中選擇在所有的匹配列中有相等值的行;
?如果有相同名字的列的數據類型不同,返回一個錯誤;
使用自然連接需要注意
?如果做自然連接的兩個表有多個字段都滿足有相同名稱和類型,那么他們 會被作為自然連接的條件;
?如果自然連接的兩個表僅是字段名稱相同,但數據類型不同,將會返回一 個錯誤;
?由于Oracle中可以進行這種非常簡單的natural join,我們在設計表時對具 有相同含義的字段需要考慮到使用相同的名字和數據類型;
(以hr用戶中的departments、locations表為例)
例
查詢部門ID,部門名稱以及他們所在的城市;Select de.department_id , de.department_name , lo.city from locations lo natural join departments de ;?Using子句創建連接(using())
?Using子句中可以指定多個列,但必須屬于and關系;例:using(employee_id,name);
?當有多個列匹配是,用using子句匹配唯一的列;
?如果某列在using中使用,那么在引用該列時不要使用表名或別名;
?Natural join 和 using 子句是互相排斥的;
(以hr用戶中的departments、locations表為例)
例
查詢location_id為1800的部門名稱以及他們所在的城市名稱,指定location_id為連接列;Select de.department_name , lo.city from locations lo join departments de using(location_id) where location_id = 1800;?SQL中的內連接(inner join)
通過inner join 來建立兩個表的連接,在內連接中使用inner join 作為表的連接,用on()子句給定連接條件。Inner join語句在性能上與其他語句沒有區別;
在用內連接做等值連接的時候,可以用using()子句來代替on子句;
(以hr用戶中的employees、departments、locations表為例)
例
查詢雇員 id 為 202 的雇員名字,部門名稱,以及工作的城市。1.等值連接
Select em.last_name,de.department_name,lo.city from employees em , departments de , locations lo where em.employee_id = 202 and em.department_id = de.department_id and de.location_id = lo.location_id;
2.內連接(Inner join)
Select em.last_name,de.department_name,lo.city from employees em inner join departments de on( em.department_id = de.department_id) inner join locations lo on( de.location_id = lo.location_id) where em.employee_id = 202;
3.在內連接中使用using子句定義等值連接
Select em.last_name,de.department_name,lo.city from employees em inner join department de using(department_id) inner join locations lo using(location_id) where em.employee_id = 202;
總結
以上是生活随笔為你收集整理的SQL语言之多表查询(oracle)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL语言(6)
- 下一篇: SQL语言之组函数(Oracle)