关系查询(Oracle)

版权声明:Mr.O版权所有 转载请标明出处 https://blog.csdn.net/qq_28189423/article/details/82946709

 

什么叫子查询?

子查询也叫嵌套查询,是指嵌入在其他sql语句中的select语句。

 

单行子查询

单行子查询是指只返回一条记录的子查询语句。

查询工资最高的人的信息

select * from emp where sal = (select max(sal) from emp);

 

显示部门平均工资低于2000的部门的员工信息

select * from emp where deptno in (select deptno from emp group by deptno having avg(sal)<2000);

 

多行子查询

多行子查询是指返回多行数据的子查询。

查询和部门10 工作相同的雇员的名字,岗位,工资,部门号

  1. 先查询部门10有哪些岗位。

select distinct(job) from emp where deptno=10;

  1. 显示这些岗位的员工

select * from emp where job in (select distinct(job) from emp where deptno=10);

 

在子查询中使用all操作符  [熟悉]

显示工资比部门30所有员工的工资都高的员工姓名    【要大于所有】

select * from emp where sal > all(select sal from emp where deptno=30);

 

在子查询中使用any操作符 [熟悉]

显示工资比部门30任意员工的工资都高的员工姓名   【只要大于一个】

select * from emp where sal > any(select sal from emp where deptno=30);

 

多列子查询

查询和SCOTT部门和岗位完全相同的所有雇员。

思路1:

使用两个子查询分别查询

select * from emp where deptno = (select deptno from emp where ename='SCOTT') and job = (select job from emp where ename='SCOTT');

 

思路2:

使用括号   oracle特有的,其他数据库不一定支持。

select * from emp where (deptno,job)= (select deptno,job from emp where ename='SCOTT');

 

使用子查询创建新表

写法:create 新表名 as select from 旧表名

create table empbak as select * from emp where 1=0;--创建空表

create table empbak2(id,name,sal) as select empno,ename,sal from emp;--创建有内容表

使用子查询自我复制数据

写法:insert into 新表名[列名] select [*,列名] from旧表。

insert into empbak(empno,ename,job,mgr,hiredate,sal,comm,deptno) select * from emp;

insert into empbak(empno,ename) select * from emp;--错误写法,值过多

insert into empbak(empno,ename) select empno,ename from emp;

合并查询

union  用于取得两个结果集的并集,自动去掉重复的行

select * from emp union select * from emp;--14条记录

 

union all 将两个结果集相加,不会去掉重复的行

select * from emp union all select * from emp;--28条记录

 

intersect  取交集,自动去掉重复的行

select * from emp where sal>800 intersect select * from emp where sal>2000;

 

minus  取差集,自动去掉重复的行

select * from emp where sal>800 minus select * from emp where sal>2000;

 

--不同表  取出相同类型的列  也可以使用   建议使用别名

select empno idno,ename idname from emp union select deptno idno,dname idname from dept;

select empno ,ename  from emp union select deptno ,dname  from dept;

笛卡尔集   交叉连接  【熟悉cross join】

在多表查询的时候,如果不带任何条件,则会出现笛卡尔集。

 

select * from emp;--14条记录

select * from dept;--4条记录

select * from emp,dept;--56条记录  隐式交叉连接

select * from emp cross join dept;--显示交叉连接

select * from salgrade;--5条记录

select * from dept,emp,salgrade;--280条记录

select * from dept cross join emp cross join salgrade;

 

笛卡尔集出现原理:

从dept中取出一条记录,分别于emp中的每一条记录匹配。

直到dept中的所有记录于emp中的所有记录全部匹配。

 

怎样避免笛卡尔集?

多表查询的条件至少不能少于表的个数-1.

 

等值连接

一个用户查询请求涉及到多个表的时候,连接多个表的条件为=时,就是等值连接查询。

 

在实际开发中,我们不可避免的需要对两张或是两张以上的表进行联合查询,比如显示雇员名字,雇员工资以及所在部门的名字。

--普通写法

select emp.ename,emp.sal,dept.dname from dept ,emp where dept.deptno = emp.deptno;

--正确写法  【不建议】

select ename,sal,dname from dept ,emp where dept.deptno = emp.deptno;

--错误写法,未明确定义列

select ename,sal,dname,deptno from dept ,emp where dept.deptno = emp.deptno;

--使用别名 [推荐写法]

select t2.ename,t2.sal,t1.dname from dept t1,emp t2 where t1.deptno = t2.deptno;

 

显示部门号为10的部门名,员工名和工资

select t1.ename,t1.sal,t2.dname from emp t1, dept t2 where t1.deptno=t2.deptno and t1.deptno=10;

 

非等值连接

一个用户查询请求涉及到多个表的时候,连接多个表的条件不是=时,就是非等值连接查询;

查询工资级别为1的员工信息。

select * from emp t1,salgrade t2 where t2.grade=1 and t1.sal between t2.losal and t2.hisal;

 

显示各个员工的姓名,工资以及工资级别。

select emp.ename,emp.sal,salgrade.grade from emp,salgrade where emp.sal between salgrade.losal and salgrade.hisal;

 

自然连接  【熟悉】

自然连接是通过对参与表关系中所有同名的属性对取等(即相等比较)来完成的,故无须自己添加连接条件

select * from emp natural join dept;--有同名列场景

select * from emp,dept where emp.deptno = dept.deptno;--效果等价

 

select * from emp natural join salgrade;--如果没有同名列 生成笛卡尔集

 

using连接  【熟悉】

相比较natural 更加灵活,可以指定多个列。

需要使用()   ()内可以有多个列,但必须是两者都有的列,使用逗号分隔。

select * from emp join dept using (deptno);

select * from emp,dept where emp.deptno = dept.deptno;--效果等价

 

on连接   【熟悉】

相比较using更加灵活,可以指定不同列名。

select * from emp join dept on emp.deptno = dept.deptno;

自连接

显示员工JONES的上级领导的姓名

select * from emp where empno = ( select mgr from emp where ename = 'JONES');

 

显示所有员工和他上级的姓名?

思路 把emp看成两张表。(worker,manager)

select worker.ename,manager.ename from emp worker,emp manager where worker.mgr = manager.empno;

 

疑惑?

只显示了13条记录,KING没有显示,因为他没有上级。

 

Oracle的连接分类【了解】

oracle的连接分为内连接和外连接。

什么叫内连接?

内连接实际上就是利用where子句对两张表形成的笛卡尔集进行筛选。是开发中用的最多的连接查询,前面部分我们学习的都是内连接。

基本语法:

select  列名1,…… from 表1 inner join 表2 on 查询条件;

 

效果等同于select 列名1,…… from 表1,表2 where 查询条件;

 

外连接

外连接分成左外联,右外联,完全外联。

 

外连接 左连接

如果左表的记录不能和右表记录进行关联也要展示。

场景:有学生5名,其中3名学生缺席考试。

 

create table stu(id number,name varchar2(20));

create table exam(id number,grade number);

insert into stu values(1,'小明');

insert into stu values(2,'张三');

insert into stu values(3,'李四');

insert into stu values(4,'王五');

insert into stu values(5,'赵六');

insert into exam values(1,90);

insert into exam values(2,100);

 

select * from stu,exam where stu.id = exam.id;--没有参加考试的学生将不能显示

select * from stu left join exam on stu.id = exam.id;--没有参加考试的学生可以显示

select * from stu,exam where stu.id = exam.id(+);--另外的写法

 

外连接 右连接

如果右表的记录不能和左表关联也要展示

场景:有插班生进行考试,插班生id在学生信息表中没有。

insert into exam values(12,100);

 

select * from stu right join exam on stu.id = exam.id; --显示插班生考试成绩

select * from stu,exam where stu.id(+) = exam.id;--另一种写法

select * from exam left join stu on stu.id = exam.id;--此种写法跟表名顺序相关,左右连互转

select * from stu,exam where exam.id = stu.id(+);--此种写法与表名的顺序无关,跟字段相关

 

外连接 完全外联

不管是否有匹配记录,都显示出来。

select * from stu full outer join exam on stu.id = exam.id;

select * from stu full join exam on stu.id = exam.id;

三表连接

查询员工的员工信息,部门名称,工资级别

select t1.*,t2.dname,t3.grade from emp t1,dept t2,salgrade t3

where t1.deptno = t2.deptno

and t1.sal between t3.losal and t3.hisal;

猜你喜欢

转载自blog.csdn.net/qq_28189423/article/details/82946709