对于查询在以前已经学过了简单查询、限定查询、查询排序,这些都属于 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开发实战经典整理