ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Oracle 关联查询

2019-06-02 18:52:48  阅读:386  来源: 互联网

标签:where 关联 emp Oracle deptno 查询 e1 select


目录

笛卡尔积

隐式内连接

显式内连接

左/右外连接

子查询

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';

 

标签:where,关联,emp,Oracle,deptno,查询,e1,select
来源: https://blog.csdn.net/wangmx1993328/article/details/90664207

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有