一、左、右连接(重点)
多表联合查询时,可能导致数据的丢失,因此要用到左右连接做到数据连接。
(+)在连接条件的左边的时候,叫右连接;(+)在连接条件的右边的时候,叫左连接
哪边缺数据,哪边放(+)
1、SELECT * FROM emp e,dept d WHERE e.deptno(+)=d.deptno; //dept表中一共有4个部门,emp表中有16行数据,分属三个部门,emp表就少了一个部门。所以(+)放在emp表
2、SELECT e.empno,e.ename,e.mgr,m.ename 上司 FROM emp e,emp m WHERE e.mgr = m.empno(+); //员工表有16行数据,但king总裁是没有上司的,所以是上司表少数据。
3、员工表、经理表、以及他们所在的部门,这个题。员工和他的领导不一定属于同一个部门吧,比如king和他的下属;king属于10号部门,但他的下属10、20、30部门都有
SELECT e.empno,e.ename,d1.*,e.mgr,m.ename 上司,d2.* FROM emp e,emp m,dept d1,dept d2 WHERE e.mgr=m.empno(+) AND d1.deptno=e.deptno AND d2.deptno=m.deptno; //运行故障:ORA-01417表可以外部连接到至多一个其他的表,此程序需要使用层次查询解决,待后续讲解
二、SQL1999(了解)
1、交叉连接(cross join),产生笛卡尔积
SELECT * FROM emp CROSS JOIN dept;
2、自然连接(nature join)
关联条件为=的,可以使用此连接,非=使用此连接,会出现笛卡尔积
SELECT * FROM emp NATURAL JOIN dept; //效果和下面代码一致
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
3、using子句
用于=关联的语句
SELECT * FROM emp JOIN dept USING(deptno);
4、on子句:用户自己编写关联条件
SELECT * FROM emp e JOIN dept d ON(e.deptno=d.deptno);
SELECT * FROM emp e JOIN salgrade s ON (e.sal BETWEEN s.losal AND s.hisal);
5、LEFT/RIGHT连接子句
LEFT/RIGHT,是哪边多就用谁
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON(e.deptno=d.deptno);
SELECT * FROM emp e,dept d WHERE e.deptno(+)=d.deptno;
三、组函数
COUNT()、MAX()、MIN()、AVG()、SUM()
SELECT COUNT(empno),MAX(sal),MIN(sal),AVG(sal),SUM(sal) FROM emp;
四、分组统计
语法格式:SELECT * FROM 表名 WHERE 关联条件 GROUP BY 分组条件 HAVING 过滤条件;
SELECT dname,COUNT(empno) FROM emp e,dept d WHERE d.deptno=e.deptno(+) GROUP BY dname;
GROUP BY后面的分组条件,必须在SELECT后面出现;同理,SELECT后面的列名,必须在GROUP BY分组条件中出现。
1、GROUP BY和HAVING后面不可使用列别名,或者*;但可使用函数
2、所以GROUP BY后面的列名,必须和SELECT的列名保持一致。
3、WHERE后面不能有组函数作为过滤条件,要使用组函数需要使用HAVING语句(不可以使用别名)
SELECT e.deptno,dname,loc,COUNT(empno),to_char(hiredate,'yyyy') FROM emp e,dept d WHERE d.deptno=e.deptno(+) GROUP BY e.deptno,dname,loc,to_char(hiredate,'yyyy') HAVING to_char(hiredate,'yyyy')>1981;
SELECT deptno,ROUND(AVG(sal)) FROM emp GROUP BY deptno HAVING ROUND(AVG(sal))>2000; //如不使用HAVING语句,会报错
SELECT e.deptno,dname,loc,COUNT(empno) FROM emp e,dept d WHERE d.deptno=e.deptno(+) GROUP BY e.deptno,dname,loc HAVING COUNT(empno)>5; //部门人数大于5的部门信息