Oracle多表查询,子查询,分页查询

🍅程序员小王的博客:程序员小王的博客

🍅 欢迎点赞 👍 收藏 ⭐留言 📝

🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕

🍅java自学的学习路线:java自学的学习路线

一、多表查询

1、多表连接基本查询

  • 定义:使用一张以上的表做查询就是多表查询,如果要查询的内容来自于2张或是N张表,这种情况下需要使 用表连接,将2张或是N张表合并成一张大表。

  • 合并后的结果:

1. 表结构(字段数):2个表的字段之和;
2. 数据行数:取决于 表连接的类型。
3. 表连接后,有冲突的字段时,需要  表名.字段名  或是  表别名.字段名  加以区分
  • 表连接的类型:内连接、外连接

  • 语法:

SELECT {DISTINCT} *|列名.. 
FROM 表名 别名,表名 1 别名
{WHERE 限制条件 ORDER BY 排序字段 ASC|DESC...}
  • 范例:查询员工表和部门表

  --范例:查询员工表和部门表
  select * from emp,dept;

我们发现产生的记录数是 56 条,我们还会发现 emp 表是 14 条,dept 表是 4 条,56 正是 emp表和 dept 表的记录数的乘积,我们称其为笛卡尔积。如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。在两张表中我们发现有一个共同的字段是 depno,depno 就是两张表的关联的字段,我们可以使用这个字段来做限制条件,两张表的关联查询字段一般是其中一张表的主键,另一张表的外键。

  select * from emp,dept where emp.deptno=dept.deptno;

关联之后我们发现数据条数是 14 条,不在是 56 条。

多表查询我们可以为每一张表起一个别名

  select * from emp e,dept d where e.deptno=d.deptno;
  • 范例:查询出雇员的编号,姓名,部门的编号和名称,地址

  --范例:查询出雇员的编号,姓名,部门的编号和名称,地址
  select e.empno,e.ename,d.deptno,d.dname,d.lo
  c from emp e,dept d 
  where e.deptno=d.deptno;

  • 范例:查询出每个员工的上级领导

  --范例:查询出每个员工的上级领导
  --分析:emp 表中的 mgr字段是当前雇员的上级领导的编号,所以该字段对 emp表产生了自身关联,
  --可以使用 mgr 字段和 empno 来关联
  select e1.ename,e1.empno,e2.ename,e2.empno
   from emp e1 ,emp e2
    where e1.mgr=e2.empno;

分析:emp 表中的 mgr字段是当前雇员的上级领导的编号,所以该字段对 emp表产生了自身关联,

可以使用 mgr 字段和 empno 来关联

  • 范例:查询出每个员工的上级领导的基础上查询该员工的部门名称

 --查询出每个员工的上级领导的基础上查询该员工的部门名称
    select e1.empno,e1.ename,e2.ename as 领导 ,d.dname 
    from emp e1,emp e2,dept d
    where e1.mgr=e2.empno
    and e1.deptno=d.deptno;

  • 范例:查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级

  --工资等级
    select * from salgrade;
    
   --查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级
 select e.empno,
 e.ename,
 decode(s.grade,    
 1,'一级',
 2,'二级',
 3,'三级',
 4,'四级',
 5,'五级') grade,
 d.dname,
 e1.empno,
 e1.ename,
 decode(s1.grade,
 1,'一级',
 2,'二级',
 3,'三级',
 4,'四级',
 5,'五级') grade
 from emp e, emp e1, dept d, salgrade s, salgrade s1
where e.mgr = e1.empno
 and e.deptno = d.deptno
 and e.sal between s.losal and s.hisal
 and e1.sal between s1.losal and s1.hisal

2、外连接

  • 外连接分类:

左外连接 left [outer]join 

右外连接 right [outer] 

全部外连接 full join

(1)左外连接

  • 语法:

select...from 表名1 left [outer] join 表名2 on 连接条件
     where ... group by ... having...order by..
  • 左外连接的特点: 必须有连接条件 以左表为主,左表和右表匹配上的数据+左表中没有匹配上的数据 两个表有顺序要求:以左表为主,右表为辅 左表中没有匹配上的数据在显示时,右表字段补空

  • 查询员工的工号、姓、收入、所在部门编号、所在的部门名称 -- 左外连接

--查询员工的工号、姓、收入、所在部门编号、所在的部门名称  -- 左外连接
select e.empno,e.ename,e.sal,e.deptno,d.dname 
from emp e
 left join dept d 
 on e.deptno=d.deptno 

(2)右外连接

  • a. 语法:

    select...from 表名1 right [outer] join 表名2 on 连接条件
    
  • b. 特点: I. 必须有连接条件 II. 最终的数据:左表+右表满足连接条件,同时右表没有符合连接条件的数据 III. 右外连接:以右表为主,只要右表中出现的数据,在结果中一定保留

(3)满连接

  • a. 语法:

    select...from 表名1 full [outer] join 表名2 on 连接条件
    
  • b. 特点: i. 必须有连接条件 ii. 最终的数据:左表+右表符合连接条件的数据+右表没有符合条件+左表没 有符合条件的数据 iii. 对表的位置没有左右要求

(4)多表连接

a.语法:

  • select...from 表名1 join 表名2 on 连接条件1 join 表名3 on 连接条件2

.....

b. 案例:

  • 查询员工的工号、姓、部门名称、所在位置。

  select employee_id,last_name,department_name,city from 
      employees e join departments d on e.department_id=d.department_id
      join locations t on d.location_id = t.location_id 

二、子查询

  • 子查询:在一个查询的内部还包括另一个查询,则此查询称为子查询。Sql的任何位置都可以加入子查询,即:在一个select语句中嵌套了另一个select语句

写在外面的select通常被称为主查询
写在里面的select通常被称为子查询

1、子查询的第一种情况:子查询的结果为单个值(一行一列)

  • 特点:直接将子查询的结果作为主查询的过滤条件

  • 案例1:查询工资最高的员工信息(工号、名、工资)

-- 案例1:查询工资最高的员工信息(工号、名、工资)
select empno,ename,sal from emp where sal=(select max(sal) from emp);

  • 案例2:查询工资大于平均工资员工信息

select empno,ename,sal from emp where sal>(select avg(sal) from emp);

2、子查询的第二种情况:子查询的结果为多个值(n行1列)

  • 特点:子查询多个数据,将多个数据看成一个结果集,直接可以参与主查询的

in(值1,值)枚举运算,注意:in中多个值来源于 子查询的结果

  • 案例:查询 和姓'King' 同部门的员工信息

--案例:查询 和姓'King' 同部门的员工信息
select  empno,ename,sal
 from emp where
  deptno=(select deptno from emp where ename='KING');

3、子查询的第三种情况:子查询结果为多行多列

  • 特点:子查询的结果为多行多列(N行n列),看做一张表,再次参与主查询的查询

  • 案例:查询工资最高的前5名员工。

--案例:查询工资最高的前5名员工。
select * from  
(select  empno,ename,sal from emp  order by sal desc)
 where rownum<=5;

  • 案例:查询工资最高的前3~5名员工。

 select tab2.* from (
 select tab1.*,rownum r from (select  empno,ename,sal from emp  order by sal desc) tab1 where rownum<=5) tab2 
 where  r>=3;

4、子查询解题思路

  • 注意:子查询的多行多列情况通常用于分页查询

sql的思路: 查询最高/低 m~m条数据

  1. 有排序,先排序,将排序的结果看作一个新的表进行二次查询 -->tab1

  2. 在tab1中获取查询数据上限:rownum<=n ,同时对rownum起别名rn --> tab2

  3. 在tab2中:rn>=m

---》合成sql

三、伪列

  • 伪列:虚列,在表中不存在此列(定义时没有指定),只有在查询时才显示。

1、rowid 【了解】

  • rowid:当前数据在硬盘中的物理地址计算的结果,唯一

  • 应用:rowid通常应用在oracle的内部;在应用层通常使用id(主键)标识数据的唯

一性

2、rownum

  • rownum:对满足条件的查询结果进行自动编号,默认从1开始,1..2..3....

  • 案例:查询薪资大于10000的员工信息:工号、名字、薪资、序号(rownum)

 select rownum,empno,ename,sal from emp;

  • 查询员工表中,前10个员工的信息(工号,姓名,薪资,序号)

 --查询员工表中,前10个员工的信息(工号,姓名,薪资,序号)
 select rownum,empno,ename,sal from emp where rownum<=10;

  • 注意:rownum只能参与 < <= =1 >=1 <=1运算 rownum不能参与 >n >=n = n运算 注意:n代表大于1的数据

  • 案例:查询员工表中,6~10编号的员工信息

 --查询员工表中,前10个员工的信息(工号,姓名,薪资,序号)
 select rownum,empno,ename,sal from emp where rownum>=6 and rownum<=10;

  • 错误的结果:没有任何数据 ,分析原因:rownum不能参与>=运算

四、分页查询

案例1:查询工资排第6~10的员工信息。

--步骤1:先按工资降序排列。
select * from emp order by sal desc;
--步骤2:查询工资排前 10 的员工,同时对 rownum起别名
select tab1.*,rownum rn from (select * from emp order by sal desc) tab1 where rownum<=10;
--步骤3:查询 rn >= 6 的员工
select tab2.* from (select tab1.*,rownum rn from 
(select * from emp order by sal desc) tab1 where rownum<=10) tab2 
where rn>=6;
--步骤4:合成SQL
 select tab2.* from (select tab1.*,rownum rn from 
 (select * from emp order by sal desc) tab1 where rownum<=10) tab2 
 where rn>=6;

  • 分页查询的关键点:

分页时,有排序,排序必须先行,构成虚表后进行2次查询 查询符合条件的前n行数据,并给rownum起别名 rn 查 rn >= m 的数据

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小王java

学习java的路上,加油!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值