Oracle 关联查询

匿名 (未验证) 提交于 2019-12-02 23:36:01
版权声明:分享是一种品质,开源是一种精神。 https://blog.csdn.net/wangmx1993328/article/details/90664207

Ŀ¼

笛卡尔积

隐式内连接

显式内连接

左/右外连接

子查询

exists 查询

rownum 行号

union 并集运算

minus 差集运算

集合运算注意事项


笛卡尔积

1、两张表数据的乘积,实际基本用不上,只是助于理解。

 select * from emp;--查询所有员工 select * from dept;--查询所有部门 select * from emp,dept;--多表查询,没加 where 条件,此时就是笛卡尔积

隐式内连接

1、在笛卡尔积的基础上加上 where 条件后就是隐式内连接。(比较常用的操作)

 select * from emp;--查询所有员工 select * from dept;--查询所有部门 --笛卡尔积加上 where 条件就是隐式内连接。查询员工及其所在的部门信息 select * from emp,dept where emp.deptno = dept.deptno; --查询员工姓名及其所在部门的位置 select e1.ename,d1.loc from emp e1,dept d1 where e1.deptno = d1.deptno;

显式内连接

1、select * from 表1 inner join 表2 on 连接条件,inner 关键字可以省略。

 --查询员工姓名及其所在部门的位置 select e1.ename,d1.loc from emp e1 inner join dept d1 on e1.deptno = d1.deptno;--必须是 on,而不是 where --查询员工姓名及其所在部门的名称 select e1.ename,d1.dname from emp e1 join dept d1 on e1.deptno = d1.deptno;--必须是 on,而不是 where

左/右外连接

1、left outer join :返回左表中的所有数据,如果右表没有对应的记录,则右表记录显示为空。outer 可省略。

2、right outer join :返回右表中的所有数据,如果左表没有对应的记录,则左表记录显示为空。outer 可省略。

 select * from emp;--查询所有员工 select * from dept;--查询所有部门  --查询每个部门的员工,同时没有员工的部门也要全部显示。必须是 on 而不是 where select * from dept d1 left outer join emp e1 on d1.deptno = e1.deptno; select * from emp e1 right outer join dept d1  on d1.deptno = e1.deptno;

3、上面是 msyql 与 oralce 的通用写法,Oracle 中还可以使用 (+) 来进行操作。

 --查询每个部门的员工,同时没有员工的部门也要全部显示。在隐式内连接的基础上使用 (+) 表示如果没有数据对应时,就显示为空 select * from dept d1,emp e1 where d1.deptno = e1.deptno(+);

子查询

1、查询语句中嵌套查询语句,用于处理复杂的查询语句,这是开发中比较常用的操作。子查询语句用括号括起来。

 --查询工资最高的员工信息 select max(sal) from emp;--第一步查询最高的工资 select * from emp where sal = (select max(sal) from emp);--第二步子查询合并  --查询与 7654 员工从事同样的工作,且工资高比 7654 员工高的员工信息 select job from emp where empno = 7654;--第一步查询 7654 号员工的工作名称 select sal from emp where empno = 7654;--第二步查询 7654 号员工的薪水 --第三步查询合并 select * from emp where job = (select job from emp where empno = 7654) and  sal > (select sal from emp where empno = 7654);

上面这种子查询有一个共同的特点:子查询的结果只有一行一列数据,所以可以放到条件语句中进行逻辑运算,如 > 、<、=、<>、!=等等。

注意:如果子查询的结果是多条数据时,则不能再放在条件语句中,而应该放在 from...的位置作为一张新的子表。

 select * from emp;--查询所有员工 select * from dept;--查询所有部门  --查询每个部门最低薪水的员工姓名,薪水,以及他所属的部门名称。 select deptno,min(sal) as minsal from emp group by deptno;--第一步分组查询各部门的最低薪水。为最低薪水设置别名,后续会使用 --使用子查询部门中等于最低薪水的员工。因为分组查询的结果是多条数据,所以需要放在 from ..的位置作为子表再次查询 select * from emp e1,(select deptno,min(sal) as minsal from emp group by deptno) t1 where e1.deptno = t1.deptno and e1.sal = t1.minsal; --设置需要显示的最终字段值 select e1.ename, e1.sal,d1.dname from emp e1,(select deptno,min(sal) as minsal from emp group by deptno) t1,dept d1         where e1.deptno = t1.deptno and e1.sal = t1.minsal and e1.deptno = d1.deptno; 

exists 查询

1、exists(查询语句):如果查询语句有结果,则返回 true,否则返回 false。

 --查询有员工的部门信息 select * from dept d1 where exists(select * from emp e1 where e1.deptno = d1.deptno);

dept 表的第一条数据会逐个对比 emp 表中的所有数据,只要有一条能匹配上,则 exists 结果为 true,部门信息就会显示,否则不显示;然后 dept 表的第二条数据开始逐个比对 emp 表,以此类推。

rownum 行号

1、rownum 是 Oracle 特有的用于表示行号的关键字,行号由系统自动生成,起始值为1,每查询出一条结果,则 rownum 自动加1.

2、rownum 因为从1开始,所以不推荐做大于判断,适用做小于等于判断。

 select * from emp;--查询所有员工 select rownum ,e1.* from emp e1;--查询所有员工,同时显示行号 select * from emp where rownum <=3;--查询前3条数据 --注意:如下所示是错误的,不会有值。因为 rownum 是从1开始,永远不会大于2,where 条件永不成立 --因为没有结果查询出来,所以 rownum 也不能加一,永远是1 select * from emp where rownum >2;

3、再次提醒,查询 SQL 执行顺序:from ...-> where ...->group by...->having ...->select ...-> order by.

 --查询 SQL 执行顺序:from ...-> where ...->group by...->having ...->select ...-> order by. --所以下面的行号是混乱的,并不是由1开始,逐个递增 select rownum,e1.* from emp e1 order by sal desc;--编写 sql 时一定要避免犯此错误

 --查询薪水最高的3个人 select * from emp e1 order by sal desc;--第一步先按薪水降序 select t1.* from (select * from emp e1 order by sal desc) t1 where rownum <=3;--第二步截取前3个人

4、rownum 还有一个重要的作用就是分页,Oracle 中分页需要借助子查询。

 select * from emp;--查询所有员工  --查询第 5-10 条数据。Oralce 分页需要借助子查询。 select * from (select rownum r,e1.* from emp e1) t where t.r>=5 and t.r<=10; select * from (select rownum r,e1.* from emp e1) t where t.r between 4 and 8;  --按薪水降序之后,然后查询第 6-12 条数据。排序后的分页,需要嵌套两层。 select * from emp order by sal desc;--第一步降序 select rownum r,t.* from (select * from emp order by sal desc) t;--第二步设置行号 --第三步根据内部行号进行分页 select * from (select rownum r,t.* from (select * from emp order by sal desc) t) t2 where t2.r between 6 and 12; 

union 并集运算

1、并集运算用于对两个结果进行合并,union 会去重,union all 不会去重。

 select * from emp;--查询所有员工 --查询薪水大于 2000,或者部门号为 30 的员工。union 会自动去重 select * from emp where sal > 2000 union select * from emp where deptno = 30; --union all 不会去重 select * from emp where sal > 2000 union all select * from emp where deptno = 30; --虽然这个需求也可以使用 or 关键字来解决,但是 or 只能是在同一张表内,而 union 并集运算可以对不同的表进行运算 select * from emp where sal >2000 or deptno = 30;

minus 差集运算

 select * from emp;--查询所有员工 --查询 1981 年入职的员工,但是不包括总裁(PRESIDENT)和经理(MANAGER) select * from emp where to_char(hiredate,'yyyy') = '1981' minus select * from emp where job = 'PRESIDENT' or job = 'MANAGER';  --虽然本需求使用 and 关键字也可以实现,但是 and 只能是表内操作,而 minus 支持不同表之间求差集 select * from emp where job != 'PRESIDENT' and job != 'MANAGER' and to_char(hiredate,'yyyy') = '1981';

集合运算注意事项

集合运算注意事项:表与表之间列的个数、类型、顺序必须一致,对不齐的可以使用 null 补齐,否则报错。

 --错误类型1:俩表之间列的个数不一致。解决办法是调整好顺序与类型 select e1.empno,e1.ename,e1.sal from emp e1 where to_char(hiredate,'yyyy') = '1981' minus select e2.empno,e2.ename from emp e2 where job = 'PRESIDENT' or job = 'MANAGER'; --错误类型2:俩表之间列的类型/顺序不一致。解决办法是 e2 表缺省的字段可以用 null 值代替 select e1.empno,e1.ename,e1.sal from emp e1 where to_char(hiredate,'yyyy') = '1981' minus select e2.empno,e2.sal,e2.ename from emp e2 where job = 'PRESIDENT' or job = 'MANAGER'; 

文章来源: https://blog.csdn.net/wangmx1993328/article/details/90664207
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!