對於查詢在以前已經學過了簡單查詢、限定查詢、查詢排序,這些都屬於 SQL 的標準語句,而上一章的單行函數,主要功能是爲了彌補查詢的不足。sql
而從多表查詢開始就正式進入到了複雜查詢部分。數據庫
多表查詢就是在一條查詢語句中,從多張表裏一塊兒取出所須要的數據。若是要想進行多表查詢,直接在 FROM 子句以後跟上多個表便可,語法以下:函數
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表名稱1[表別名1],表名稱2[表別名2],... [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC,排序的字段2 ASC|DESC,...];
下面就將採用 emp 表和 dept 表一塊兒進行多表查詢,查詢以前多作一個步驟,先肯定 emp 和 dept 表中的數據量分別有多少,可使用 COUNT() 函數統計性能
範例:統計 emp 表中的數據量 (14 行記錄)學習
SELECT COUNT(*) FROM emp;
範例:統計 dept 表中的數據量 (4行記錄)spa
SELECT COUNT(*) FROM dept;
範例:如今查詢全部的僱員和部門的所有詳細信息code
SELECT COUNT(*) FROM emp,dept;
範例:利用等值條件來處理笛卡爾積排序
SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno;
範例:查看 sh.sales 表的數據量 (918843條記錄)開發
SELECT COUNT(*) FROM sh.sales;
範例:查看 sh.costs 表的數據量 (82112條記錄)學習資料
SELECT COUNT(*) FROM sh.costs;
範例:若是如今直接將這兩張表進行多表查詢,那麼來觀察問題
SELECT COUNT(*) FROM sh.sales,sh.costs;
範例:查詢每一個僱員的編號、姓名、職位、基本工資、部門名稱、部門位置信息
SELECT emp.empno,emp.ename ,emp.job,emp.sal,dept.dname,dept.loc FROM emp,dept WHERE emp.deptno = dept.deptno
SELECT e.empno, e.ename, e.job, e.sal, d.dname, d.loc FROM emp e, dept d WHERE e.deptno=d.deptno;
範例:查詢出每一個僱員的編號、姓名、僱傭日期、基本工資、工資等級
SELECT e.empno, e.ename, e.hiredate, e.sal, s.grade FROM emp e, salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;
範例:爲了更加清楚的顯示出工資等級的信息,如今但願能夠按以下格式進行替換顯示:
grade = 1 : 顯示爲 「 E等工資 」
grade = 2 : 顯示爲 「 D等工資 」
grade = 3 : 顯示爲 「 C等工資 」
grade = 4 : 顯示爲 「 B等工資 」
grade = 5 : 顯示爲 「 A等工資 」
SELECT e.empno, e.ename, e.hiredate, e.sal, DECODE(s.grade,1,'E等工資',2,'D等工資',3,'C等工資',4,'B等工資',5,'A等工資') grade FROM emp e, salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;
範例:查詢出每一個僱員的姓名、職位、基本工資、部門名稱、工資等級
SELECT e.ename, e.job, e.sal, d.dname, DECODE(s.grade,1,'E等工資',2,'D等工資',3,'C等工資',4,'B等工資',5,'A等工資') grade FROM emp e, dept d, salgrade s WHERE e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal;
INSERT INTO emp(empno, ename, job, mgr, hiredate, sal, comm, deptno) VALUES(8888,'李華華','CLERK',7369,SYSDATE,800,100,null);
SELECT * FROM emp;
範例:使用等值鏈接
SELECT * FROM emp e, dept d WHERE e.deptno = d.deptno;
範例:使用左外鏈接,顯示僱員編號是8888的信息
SELECT * FROM emp e, dept d WHERE e.deptno = d.deptno(+);
範例:使用右外鏈接,顯示部門編號爲40的信息
SELECT * FROM emp e, dept d WHERE e.deptno(+) = d.deptno;
SELECT * FROM emp;
範例:查詢出每一個僱員的編號、姓名及其上級領導的編號、姓名
SELECT e.empno eno, e.ename ename, m.empno mno, m.ename mname FROM emp e, emp m WHERE e.mgr = m.empno;
如今表中一共有15條記錄,可是隻有14條的記錄顯示,等值鏈接在沒有條件知足的時候,是不可能有數據顯示的。
在 emp 表中 king 這個僱員是沒有領導的,這個時候就必須考慮外鏈接。
SELECT e.empno eno, e.ename ename, m.empno mno, m.ename mname FROM emp e, emp m WHERE e.mgr = m.empno(+);
對於沒有領導信息的僱員,對應的領導信息,所有使用 null 進行表示
範例:查詢出在1981年僱員的所有僱員的編號、姓名、僱傭日期(按照年-月-日顯示)、工做、領導姓名、僱員月工資、僱員年工資(基本工資+獎金)、僱員工資等級、部門編號、部門名稱、部門位置、而且要求這些僱員的月基本工資在1500~3500之間,將最後的結果按照年工資的降序排列,若是年工資相等,則按工做進行排序
SELECT e.empno, e.ename, e.hiredate, e.sal, (e.sal+NVL(e.comm,0))*12 income FROM emp e WHERE TO_CHAR(e.hiredate,'yyyy') = '1981' AND e.sal BETWEEN 1500 AND 3500;
SELECT e.empno, e.ename, e.hiredate, e.job, e.sal, (e.sal+NVL(e.comm,0))*12 income, m.ename mname FROM emp e, emp m WHERE TO_CHAR(e.hiredate,'yyyy') = '1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr = m.empno(+);
SELECT e.empno, e.ename, e.hiredate, e.job, e.sal, (e.sal+NVL(e.comm,0))*12 income, m.ename mname, d.deptno dno, d.dname dname, d.loc FROM emp e, emp m, dept d WHERE TO_CHAR(e.hiredate,'yyyy') = '1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr = m.empno(+) AND e.deptno = d.deptno;
SELECT e.empno, e.ename, e.hiredate, e.job, e.sal, (e.sal+NVL(e.comm,0))*12 income, m.ename mname, d.deptno dno, d.dname dname, d.loc, s.grade FROM emp e, emp m, dept d,salgrade s WHERE TO_CHAR(e.hiredate,'yyyy') = '1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr = m.empno(+) AND e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal;
SELECT e.empno, e.ename, e.hiredate, e.job, e.sal, (e.sal+NVL(e.comm,0))*12 income, m.ename mname, d.deptno dno, d.dname dname, d.loc, s.grade, DECODE(s.grade,1,'E等工資',2,'D等工資',3,'C等工資',4,'B等工資',5,'A等工資') 工資等級 FROM emp e, emp m, dept d,salgrade s WHERE TO_CHAR(e.hiredate,'yyyy') = '1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr = m.empno(+) AND e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal;
SELECT e.empno, e.ename, e.hiredate, e.job, e.sal, (e.sal+NVL(e.comm,0))*12 income, m.ename mname, d.deptno dno, d.dname dname, d.loc, s.grade, DECODE(s.grade,1,'E等工資',2,'D等工資',3,'C等工資',4,'B等工資',5,'A等工資') 工資等級 FROM emp e, emp m, dept d,salgrade s WHERE TO_CHAR(e.hiredate,'yyyy') = '1981' AND e.sal BETWEEN 1500 AND 3500 AND e.mgr = m.empno(+) AND e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal; ORDER BY income DESC, e.job;
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表1 表別名1 [CROSS JOIN 表2 表別名2]| [NATURAL JOIN 表2 表別名2]| [JOIN 表2 USING(關聯列名稱)]| [JOIN 表2 ON(關聯條件)]| [LEFT|RIGHT|FULL OUTER JOIN 表2 ON(關聯條件)] [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC, 排序的字段2 ASC|DESC,...];
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表1 表別名1 [CROSS JOIN 表2 表別名2]| [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC, 排序的字段2 ASC|DESC,...];
範例:使用交叉鏈接查詢信息
SELECT * FROM emp CROSS JOIN dept;
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表1 表別名1 [NATURAL JOIN 表2 表別名2]| [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC, 排序的字段2 ASC|DESC,...];
範例:使用天然鏈接查詢信息
SELECT * FROM emp NATURAL JOIN dept;
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表1 表別名1 [JOIN 表2 USING(關聯列名稱)]| [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC, 排序的字段2 ASC|DESC,...];
範例:使用 USING 子句查詢信息
SELECT * FROM emp JOIN dept USING(deptno);
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表1 表別名1 [JOIN 表2 ON(關聯條件)]| [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC, 排序的字段2 ASC|DESC,...];
範例:使用 ON 子句查詢信息
SELECT * FROM emp e JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal);
SELECT [DISTINCT] *|列名稱 [AS][列別名],列名稱 [AS][列別名],... FROM 表1 表別名1 [LEFT|RIGHT|FULL OUTER JOIN 表2 ON(關聯條件)] [WHERE 條件(s)] [ORDER BY 排序的字段1 ASC|DESC, 排序的字段2 ASC|DESC,...];
範例:實現右外鏈接
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON (e.deptno = d.deptno);
範例: 實現左外鏈接
SELECT * FROM emp e LEFT OUTER JOIN dept d ON (e.deptno = d.deptno);
範例:實現全外鏈接
SELECT * FROM emp e FULL OUTER JOIN dept d ON (e.deptno = d.deptno);
查詢語句 [UNION | UNION ALL | INTERSECT | MINUS] 查詢語句 ...
範例:並集操做:UNION , UNION ALL
SELECT * FROM dept;
SELECT * FROM dept WHERE deptno = 10;
這個時候兩個查詢結果返回的列的結構相同。
SELECT * FROM dept UNION SELECT * FROM dept WHERE deptno = 10;
第一個查詢已經包含了第二個查詢的內容,因此重複數據不顯示了。
範例:使用 UNION ALL 顯示所有
SELECT * FROM dept UNION ALL SELECT * FROM dept WHERE deptno = 10;
範例:查詢全部銷售人員和辦事人員的信息
SELECT * FROM emp WHERE job = 'SALESMAN' OR job = 'CLERK';
SELECT * FROM emp WHERE job IN ('SALESMAN', 'CLERK');
SELECT * FROM emp WHERE job = 'SALESMAN' UNION SELECT * FROM emp WHERE job = 'CLERK'
範例:使用 MINUS 執行差集操做
SELECT * FROM dept MINUS SELECT * FROM dept WHERE deptno = 10;
7.6.3 交集操做
範例:使用 INTERSECT 執行交集操做
SELECT * FROM dept INTERSECT SELECT * FROM dept WHERE deptno = 10;
說明:本學習資料是根據李興華的Oracle開發實戰經典整理