視頻課程:李興華 Oracle從入門到精通視頻課程 學習者:陽光羅諾 視頻來源:51CTO學院 總體內容: 一、認識多表查詢 所謂的多表查詢就是同時從多張表中取出數據並且顯示的一種操作。語法只是做了一些簡單的修改。 語法格式: 於是我們就可以按照這樣子的語法結構來實現多表查詢。本次將會使用emp和d ...
視頻課程:李興華 Oracle從入門到精通視頻課程
學習者:陽光羅諾
視頻來源:51CTO學院
總體內容:
- 多表查詢的意義以及基本問題。
- 表的連接查詢
- SQL:1999語法標準對多表查詢的支持。
- 數據的集合操作。
一、認識多表查詢
所謂的多表查詢就是同時從多張表中取出數據並且顯示的一種操作。語法只是做了一些簡單的修改。
語法格式:
1 【③選出所需要的數據列】SELECT [DISTINCT] * 列[別名],列[別名],列[別名]······
2
3 【①確定數據來源(行和列的集合)】FROM 表名稱 [別名],表名稱 [別名],······
4
5 【②篩選數據行】[WHERE 限定條件] 此時的條件可以是多個語法結構。
6
7 【④數據排序】[ORDER BY 排序欄位 [ASC|DESC] 可以設置多個]
於是我們就可以按照這樣子的語法結構來實現多表查詢。本次將會使用emp和dept兩張表格進行多表的查詢。於是在查詢之前,先做一些準備,在資料庫中有一個COUNT()函數,這個函數的主要作用:可以統計出一張數據表中的數據量。
準備查詢一:查詢dept表中的數據量。(4行記錄)
代碼示例:
1 select count(*) from dept;
準備查詢二:查詢emp表中的數據量。(14行記錄)
代碼示例:
1 select count(*) from emp;
目前兩張表的記錄加起來,總記錄是18行。根據語法格式可以實現多表的查詢。
範例:實現emp與dept的多表查詢。
發現在每一行emp表中的記錄出現了4次,而4次是dept表中的數據量,所以最終產生了14行X4行=56行記錄。
之所以出現這樣的情況,主要用於資料庫的產生原理有關———數學的集合。在這樣子的集合操作裡面,我們會將這兩個集合(數據表)統一查詢,作為乘法的形式出現。結果一定會產生積————笛卡兒積。在任何情況下要進行的多表查詢中都一定會存在有笛卡兒積的問題。事實上,這些積的產生對用戶而言是沒有實質上的用處,需要想辦法去消除積。
如果要消除積,就必須有關聯欄位。
很明顯,現在emp和dept數據表之中存在有關聯欄位(大部分情況下,都習慣將關聯欄位設置為同名)。我們就可以使用關聯欄位來消除笛卡兒積。
代碼示例:
1 SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
可以得出結論:只要是多表查詢,這多張表之間就一定要存在有關聯關係。沒有關聯關係的表是不可能多表查詢的。
但是就目前而言,代碼依然是存在有問題。
此時進行欄位訪問的時候採用的是“表名稱.欄位名稱”,如果是表名稱短的話,一般是沒有什麼問題的。而如果表名稱長了,例如:“yuzhou_yinghexi_diqiu_yazhoudalu_shanghai_ren”,所以在進行多表查詢的時候,強烈建議使用別名。
實際上笛卡兒積的存在對於整個程式的影響是相當巨大的,即使現在可以消除顯示的笛卡兒積,但是從本質上來講,永遠無法避免笛卡兒積。
例如:在Oracle的樣本數據中有sh的大數據用戶。
分析一:取得costs表中的記錄數。
SELECT COUNT(*) FROM costs;
多表查詢操作案例(分析過程)
範例:要求查詢出每一個雇員的編號、姓名、職位、基本工資、部門名稱、部門位置。
·確定要使用的數據表
- emp表:雇員的編號、姓名、職位、基本工資
- dept表:部門名稱、部門位置
·確定已知的關聯欄位
- 雇員與部門關聯:emp.deptno = dept.deptno
第一步:查詢出每一個雇員的編號、姓名、職位、基本工資。現在只需要使用emp一張數據即可。
代碼示例:
1 select e.empno,e.ename,e.job,e.sal from emp e;
第二步:查詢出每一個雇員對應的部門信息。需要引入dept表(引入表的時候一定要考慮有關聯),這兩張表直接可以利用dept表deptno欄位關聯,所以需要利用WHERE子句來消除笛卡兒積。
代碼示例:
1 select e.empno,e.ename,e.job,e.sal,d.dname,d.loc from emp e,dept d WHERE e.deptno=d.deptno;
以上的操作屬於之前基本概念的加強,並且給出了明確的關聯欄位。可是很多的查詢是不會明確給出關聯欄位的。
範例:要求查詢出每一個雇員的編號、姓名、職位、基本工資、工資等級。
- 確定要使用的數據表。
emp表:雇員的編號、姓名、職位、基本工資
salgrade表:工資等級
- 確定已知的關聯欄位。
雇員與工資等級:emp.sal BETWEEN salgrade.losal AND salgrade.hisal;
第一步:查詢出每一個雇員的編號、姓名、職位、基本工資。現在只需要使用emp一張數據即可。
代碼示例:
1 select e.empno,e.ename,e.job,e.sal from emp e;
第二步:增加salgrade表,增加了數據表之後,就需要引入WHERE子句來消除掉笛卡兒積。
代碼示例:
1 select e.empno,e.ename,e.job,e.sal,s.grade
2
3 from emp e,salgrade s
4
5 WHERE e.sal BETWEEN s.losal AND s.hisal;
範例:查詢每一個雇員的編號、姓名、職位、基本工資、部門名稱、工資等級。
確定所需要的數據表:
- emp表:編號、姓名、職位、基本工資
- dept表:部門名稱
- salgrade表:工資等級
確定相互關聯的欄位:
- 雇員與部門:emp.deptno = dept.deptno;
- 雇員與工資等級:emp.sal BETWEEN salgrade.losal AND salgrade.hisal;
第一步:查詢每一個雇員的編號、姓名、職位、基本工資。
代碼示例:
1 select e.empno,e.ename,e.job,e.sal
2
3 from emp e;
第二步:加入部門名稱,增加一張表就增加陽光條件就消除笛卡兒積。
代碼示例;
1 select e.empno,e.ename,e.job,e.sal,d.dname
2
3 from emp e,dept d
4
5 WHERE e.deptno= d.deptno;
第三步:加入工資等級信息,與原始的消除笛卡兒積條件應該同時滿足,所以使用AND 來連接。
示例代碼:
1 select e.empno,e.ename,e.job,e.sal,d.dname
2
3 from emp e,dept d,salgrade s
4
5 WHERE e.deptno= d.deptno and e.sal BETWEEN s.losal AND s.hisal;
表的連接
實際上對於兩張數據表進行多表查詢,對於消除笛卡兒積來講主要是依靠連接模式來處理的,而對於表的連接模式在資料庫的定義上,有兩種:
l 內連接:在之前都利用WHERE子句消除了笛卡兒積,這就屬於內連接。
l 外連接:分為三種:左外連接、右外連接、全外連接。
為了方便更好的觀察到連接的區別,現在已經在dept表中提供了一個沒有雇員的部門(40部門),同時在emp表中增加一個沒有部門的雇員。
代碼示例:
觀察1:內連接的實現效果。
觀察2:使用左(外)連接。希望所有的雇員信息都顯示出來。即使沒有對應的部門。
代碼示例:
1 SELECT e.empno,e.ename,d.deptno,d.dname
2
3 FROM emp e,dept d
4
5 WHERE e.deptno=d.deptno(+);
此時沒有部門的雇員信息出現了,也就是說左表的數據全部顯示了。
觀察3:使用右(外)連接。將所有的部門信息顯示出來。
代碼示例:
1 SELECT e.empno, e.ename, d.deptno, d.dname
2
3 FROM emp e, dept d
4
5 WHERE e.deptno(+) = d.deptno;
內連接就是所有滿足關聯關係的數據出現,不滿足的不出現,外連接就是指定一張數據表中的內容全部都顯示,但是沒有對應的其他的表的數據內容位null。
在Oracle中使用了“(+)”來控制連接方式。
左外連接:關聯欄位1=關聯欄位2(+);
右外連接:關聯欄位1(+)=關聯欄位2;
大部分情況下一般都只會考慮內連接,但是當你發現所需要的數據不全的時候就可以考慮外連接。、
範例:查詢每一個雇員的編號、姓名、職位、領導姓名、領導職位。
確定所需要的數據表。
- emp表(雇員信息):編號、姓名、職位。
- emp表(領導信息):領導姓名、領導職位。
確定已知的關聯欄位。
- 雇員與領導:emp.mgr = memp.empno
第一步:查詢出每一個雇員的編號、姓名、職位。
代碼示例:
1 SELECT e.empno,e.ename,e.job FROM emp e;
第二步:加入領導信息。需要引入自身關聯,而後消除笛卡兒積。
代碼示例:
1 SELECT e.empno,e.ename,e.job,m.ename,m.job
2
3 FROM emp e, emp m
4
5 WHERE e.mgr=m.empno;
第三步:發現emp表(雇員信息)數據不完整,因為不滿足於等值關聯判斷,所以要讓雇員信息顯示完整,則必須使用外連接控制。
SQL:1999語法定義
對於數據表的連接操作,從實際使用來講各個資料庫都是有所支持的,所以對於所有的資料庫,進行表連接最好的做法是利用以下的語法可以完成:
語法:
1 SELECT [DISTINCT] * | 列 [別名] ,列 [別名],······
2
3 FROM 表1 [別名]
4
5 [CROSS JOIN 表2 [別名]]
6
7 [NATURE JOIN 表2 [別名]]
8
9 [JOIN 表2 [別名] ON (條件)| USING(關聯欄位)]
10
11 [LEFT | RIGHT | FULL OUTER JOIN ON(條件)表2];
個人在進行表連接的時候,如果是內連接一定使用等值判斷,如果是外連接才會使用LEFT、RIGHT、OUTER等操作。
- 交叉連接:目的是產生笛卡兒積
語法:
1 SELECT [DISTINCT] * | 列 [別名] ,列 [別名],······
2
3 FROM 表1 [別名] [CROSS JOIN 表2 [別名]]
範例:實現交叉連接
代碼示例:SELECT * FROM emp CROSS JOIN dept;
- 自然連接:利用關聯欄位自己進行消除笛卡兒積(只要欄位名稱相同即可)
語法:
1 SELECT [DISTINCT] * | 列 [別名] ,列 [別名],······
2
3 FROM 表1 [別名] [NATURE JOIN 表2 [別名]]
範例:實現自然連接。(內連接)
代碼示例:
1 SELECT * FROM emp NATURAL JOIN dept;
- 使用自然連接是要求兩張表的欄位名稱相同,但是如果說有一天不相同了呢?或者兩張表中中有兩組欄位都是重名的。所以這種使用ON子句指定關聯條件,而利用USING子句設置關聯欄位。
範例:利用USING子句設置關聯欄位實現自然連接。
1 SELECT * FROM emp JOIN dept USING(deptno);
範例:利用ON子句設置關聯條件。
1 SELECT * FROM emp e JOIN dept d ON(e.deptno=d.deptno);
外連接
1 SELECT [DISTINCT] * | 列 [別名] ,列 [別名],······
2
3 FROM 表1 [別名] [LEFT | RIGHT | FULL OUTER JOIN ON(條件)表2];
範例:觀察左外連接
1 SELECT * FROM emp e LEFT OUTER JOIN dept d ON (e.deptno=d.deptno);
範例:觀察右外連接。
1 SELECT * FROM emp e RIGHT OUTER JOIN dept d ON (e.deptno=d.deptno);
範例:全外連接
代碼示例:
1 SELECT * FROM emp e FULL OUTER JOIN dept d ON (e.deptno=d.deptno);
部分截圖:
數據集合操作
數學集合:交集、並集、補集。
每一次查詢實際上都會返回數據集合,所以返回的結果可以使用UNION、UNION ALL、MINUS、INTERSECT來實現集合的操作。
1 SELECT [DISTINCT] * 列[別名],列[別名],列[別名]······
2
3 FROM 表名稱 [別名],表名稱 [別名],······
4
5 [WHERE 限定條件] 此時的條件可以是多個語法結構。
6
7 [ORDER BY 排序欄位 [ASC|DESC] 可以設置多個]
8
9 UNION | UNION ALL | INTERSECT | MINUS
10
11
12
13 SELECT [DISTINCT] * 列[別名],列[別名],列[別名]······
14
15 FROM 表名稱 [別名],表名稱 [別名],······
16
17 [WHERE 限定條件] 此時的條件可以是多個語法結構。
18
19 [ORDER BY 排序欄位 [ASC|DESC] 可以設置多個]