【oracle表基本查询 -介绍】
在我们讲解的过程中我们利用 scott 用户存在的几张表(emp, dept)为大家
演示如何使用 select 语句,select语句在软件编程中非常有用,希望大家
好好的掌握。
pl/sql清屏命令 -- clear
做销售的一半都有奖金~
set timing on; -- 打开显示操作时间的开关!就是用了多少时间。
疯狂复制法:
create table users(userid varchar2(20),
username varchar2(30),
userPss varchar2(20)
);
insert into users values ('a001', '单顺平sfaa','[email protected]');
insert into users (userid, username, userpss) select * from users;
select count(*) from users;
查看表结构:desc dept;
查询所有列:select * from dept;(查询数据库切记动不动就用*)
查询指定列:select ename, sal, job, deptno from emp;
如何取消重复行:select distinct deptno, job from emp;
?查询SMITH的薪水【年底发双薪,故*13】,工作,所在部门。
select sal*13, ename from emp;
取个别名儿让结果集好看一点
select sal*13 "年工资", ename "雇员姓名" from emp;
另外,奖金不给算上是不合理的【不仅能运用乘法,还能用加法】
select sal*13+comm*13 "年工资", ename from emp;
还是不够完美,突然发现 SMITH 年工资变为空了,为什么呢?先来看看这条语句的结果
select sal*13+comm*13 "年工资", ename, comm from emp;
隆重推荐一个处理 null 值的 “nvl函数” -- 判断是否为空~
如果comm查出来的值为空值,则用0替代;如果comm不为空,则用comm本身的值~
select sal*13+nvl(comm, 0)*13 "年工资", ename from emp;
【使用 where 子句】
?如何显示工资高于3000的员工
select ename,sal from emp where sal>3000;
?如何超找1982.1.1后入职的员工[【可以通过修改注册表修正时间问题】
select ename,sal from emp where hiredate>'1-1月-1982';
?如何显示工资在2000到2500的员工情况【多个条件之间应该用and隔开】
select ename,sal from emp where sal>=2000 and sal<=2500;
如何使用like操作符
%: 表示0到多个字符
_: 表示任意单个字符
?如何显示首字符为S的员工姓名和工资
select ename, sal from emp where ename like 'S%';
?如何显示第三个字符为大写O的所有员工的姓名和工资
select ename, sal from emp where ename like '__O%';
在where 条件中使用 in
?如何显示empno为123,345,800,.. 的雇员情况
select * from emp where empno in(7369,7499,7934,321);
使用is null 的操作符
?如何显示没有上级的雇员的情况
select * from emp where mgr is null;
【使用逻辑操作符号】
?查询工资高于500或是岗位为MANGER的雇员,同时还要满足他们的姓名
首写字母为大写的J。
select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';
使用 order by 子句【默认按从低到高的顺序排列】
?如何按照工资的从低到高的顺序显示雇员的信息
select * from emp order by sal;【升序】
select * from emp order by sal asc;【升序】
select * from emp order by sal desc;【降序】
?按照部门编号升序而雇员的工资降序排列【这个很有用】
select * from emp order by deptno asc, sal desc;
select * from emp order by deptno asc, hiredate desc;
使用列的别名排序【注意:别名需要使用双引号圈中】
select ename, (sal+nvl(comm,0))*12 "年薪" from emporder by "年薪" asc;
【oracle表复杂查询】
说明:
在实际应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,
现在我们给大家介绍较为复杂的select语句。
数据分组-max,min,avg,sum,count
?如何显示所有员工中最高工资和最低工资
select max(sal),min(sal) from emp;
select ename,sal from emp where sal=max(sal);【wrong!】
ORA-00934: 此处不允许使用分组函数
select ename,sal from emp where max(sal)=sal;【wrong, too!】
ORA-00934: 此处不允许使用分组函数
select ename,sal from emp where sal=(select max(sal) from emp);
select ename,max(sal) from emp;
ORA-00937: 非单组分组函数
【注意: 如果列里面有一个分组函数,其他都必须是分组函数!】
?显示所有员工的平均工资和工资总和
?计算共有多少员工
select count(*) from emp;
扩展要求:
?请显示工资最高的员工的名字,工作岗位
select ename,job from emp where sal=(select max(sal) from emp);
?请显示工资高于平均工资的员工信息
select * from emp where sal>(select avg(sal) from emp);
【oracle表复杂查询】
group by 用于对查询的结果分组统计,having子句用于限制分组显示结果。
?如何显示每个部门的平均工资和最高工资【分组的字段必须出现!】
select avg(sal),max(sal),deptno from emp group by deptno;
?显示每个部门的每种岗位的平均工资和最低工资
select min(sal),avg(sal),max(sal),deptno,job from empgroup by deptno,job;
?显示平均工资低于2000的部门号和他的平均工资
select avg(sal),max(sal),deptno from emp group by deptnohaving avg(sal)>2000;
对数据分组的总结:
①分组函数只能出现在选择列表、having、order by子句中;
②如果在select语句中同时包含group by,having,order by 那么
他们的顺序是 group by, having, order by
【顺序很重要,不可能是先有having再有order by,因为首先分组了过后才
可能对分组的结果进行筛选,筛选完之后还可以进行排序】
select avg(sal),max(sal),deptno from emp group by deptno having avg(sal)>2000 order by avg(sal);
③在选择列中如果有列、表达式和分组函数,那么这些列和表达式
必须有一个出现在group by子句中,否则就会出错。
如:select deptno,avg(sal),max(sal) from emp group by deptnohaving avg(sal)<2000;
这里deptno就一定要出现在group by 中。
【oracle表复杂查询 -- 多表查询】
说明:
多表查询是指基于两个和两个以上的表或是视图的查询。在实际应用中,
查询单个表可能不能满足你的需求,(如显示sales部门位置和其员工的姓名),
这种情况下需要使用到(dept表和emp表)
?显示雇员名,雇员工资及所在部门的名字【笛卡尔集】
select a1.ename,a1.sal,a2.dname from emp a1,dept a2;【产生笛卡尔集】
select t1.ename,t1.sal,t2.dname from emp t1,dept t2where t1.deptno=t2.deptno;【取别名】
select emp.ename,emp.sal,dept.dname from emp,dept where emp.deptno=dept.deptno;【不取别名】
?如何显示部门号为10的部门名、员工名和工资
select t2.dname,t1.ename,t1.sal,t2.deptno from emp t1,dept t2where t1.deptno=t2.deptno and t1.deptno=10;
?显示各个员工的姓名,工资,及其工资的级别
select t1.ename,t1.sal,t2.grade from emp t1,salgrade t2where t1.sal between t2.losal and t2.hisal;
扩展要求【多表里面排序也是不成问题的~】:
?显示雇员名,雇员工资及所在部门的名字,并按部门排序。
select t1.ename,t1.sal,t2.dname from emp t1,dept t2 where t1.deptno=t2.deptno order by t1.deptno;
---------------------------------------------------
注意:在数据库里面有一个特别重要的原则!
如果你是两张表联合查询,至少有一个条件才能排除笛卡尔集;
如果是三张表,则至少有两个条件才能排除笛卡尔集;
也就是说:多表查询的条件至少不能少于表的个数减1,否则必错。
自连接
自连接是指在同一张表的连接查询。
?显示某个员工的上级领导的姓名。
比如显示“FORD”的上级
select worker.ename,boss.ename from emp worker,emp bosswhere worker.mgr=boss.empno and worker.ename='FORD';
【oracle表复杂查询 -- 子查询【一个select语句嵌套在另一个select语句中】】
什么是子查询:
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
1.单行子查询:单行子查询是指值返回一行数据的子查询语句。
请思考:如何显示与SMITH同一个部门的所有员工?
①首先得到SMITH所属的部门号(尽可能把优化条件放于此)
select deptno from emp where ename='SMITH';
②显示与SIMTH同一个部门的所有员工
select * from emp where deptno=(select deptno from emp where ename='SMITH');
2.多行子查询:多行子查询指返回多行数据的子查询【一般用关键字in】
请思考:如何查询和部门10的工作相同的雇员的名字、岗位、工作、部门号。
select distinct job from emp where deptno=10;
select * from emp where job in (select distinct job from emp where deptno=10);
3.在多行子查询中使用all 操作符
请思考:如何显示工资比部门30的所有员工的工资高的员工的 姓名、工资 和 部门号
select ename,sal,deptno from emp where sal>all(select salfrom emp where deptno=30);
第二种方法:【这种方法效率较高】
select max(sal) from emp where deptno=30;
select * from emp where sal>(select max(sal) from emp where deptno=30);
4.在多行子查询中使用 any 操作符【只要比其中一个的工资高就行】
请思考:如何显示工资比部门30的任意一个员工的工资高的员工的姓名、工资
和部门号
select ename,sal,deptno from emp where sal>any(select salfrom emp where deptno=30);
5.多列子查询:单行子查询是指子查询只返回单列、单行数据,多行子查询
是指返回多行单列数据,都是针对单列而言的,而多列子查询则是指查询返回
多个列数据的子查询语句。
请思考:如何查询与smith的部门和岗位完全相同的所有雇员。
select deptno,job from emp where ename='SMITH';
【这两个列的顺序一定要是一致的】
select * from emp where (deptno,job)=(select deptno,job from emp where ename='SMITH');
6.在from子句中使用子查询
请思考:如何显示高于自己部门平均工资的员工的信息
解题思路:
①首先查询出各个部门的平均工资和部门号
select deptno,avg(sal) mysal from emp group by deptno;
②把上面的查询看做是一张子表而存在
select t1.ename,t1.sal,t1.deptno, t2.mysal from emp t1,(select deptno,avg(sal) mysal
from emp group by deptno) t2 where t1.deptno=
t2.deptno and t1.sal>t2.mysal;
7.在from子句中使用子查询
这里需要说明的当在 from 子句中使用子查询时,该子查询会被作为
一个视图来对待,因此叫做内嵌视图,当在from子句中使用子查询时,
必须给子查询指定别名。建议不要用as【一般给列取别名儿的时候
喜欢用as,但给表取别名儿的时候不要加as,加了就过不去】
8.分页查询:按雇员的id号升序取出。【oracle分页一共有种方式】【内嵌视图】
①rownum 分页
select * from emp;
②显示rownum[oracle分配的]
select t1.*,rownum rn from (select * from emp) t1;
【后接and rownum>=6的话不生效,用between..and也没有用~】
【二分机制速度很好,就是理解起来比较难】
select t1.*,rownum rn from (select * from emp) t1 where rownum<=10;
【完成 -- 再做一次子查询】
select * from (select t1.*,rownum rn from (select *from emp) t1 where rownum<=10) where rn>=6;
注意【当一个公式来记忆即可】:
a.指定查询列,只需要修改最里层的子查询;
select * from (select t1.*,rownum rn from (select ename,sal
from emp) t1 where rownum<=10) where rn>=6;
b.如何排序,也只需要修改最里层的子查询即可【order by 默认升序排】;
select * from (select t1.*,rownum rn from (select ename,sal
from emp order by sal) t1 where rownum<=10) where rn>=6;
c.如何更改分页参数,也只需要修改最里层的子查询即可;
select * from (select t1.*,rownum rn from (select ename,sal
from emp order by sal) t1 where rownum<=9) where rn>=4;
9.用查询结果创建新表【能够创建出一张新表,而且里面会有数据】
这个命令是一种快捷的建表方法。
create table mytable (id,name,sal,job,deptno) as select empno,ename,sal,job,deptno from emp;
create table myemp2 (id,ename,sal) as select empno,ename,sal from emp;
10.合并查询
有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号
union, union all, intersect, minus。
①union:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动
去掉结果集中重复行。
select ename,sal,job from emp where sal>2500 union select ename,sal,job from emp where job='MANAGER';
②union all:该操作赋予union相似,但是他不会取消重复行,而且不会排序。
select ename,sal,job from emp where sal>2500 union all select ename,sal,job from emp wherejob='MANAGER';
③intersect:使用该操作符用于取得两个结果集的交集。
select ename,sal,job from emp where sal>2500 intersect select ename,sal,job from emp where job='MANAGER';
④minus:使用该操作符用于取得两个结果集的差集,他只会显示存在第一个
集合中,而不存在第二个集合中的数据。
select ename,sal,job from emp where sal>2500 minus select ename,sal,job from emp where job='MANAGER';
-----------------------------------------------------------------
SQL> select ename,sal,job from emp where sal>2500 minus
2 select ename,sal,job from emp where job='MANAGER';
ENAME SAL JOB
---------- ---------- ---------
FORD 3000 ANALYST
KING 5000 PRESIDENT
SCOTT 3000 ANALYST
SQL> select ename,sal,job from emp where sal>2500;
ENAME SAL JOB
---------- --------- ---------
JONES 2975.00 MANAGER
BLAKE 2850.00 MANAGER
SCOTT 3000.00 ANALYST
KING 5000.00 PRESIDENT
FORD 3000.00 ANALYST
SQL> select ename,sal,job from emp where job='MANAGER'
2 ;
ENAME SAL JOB
---------- --------- ---------
JONES 2975.00 MANAGER
BLAKE 2850.00 MANAGER
CLARK 2450.00 MANAGER
【创建数据库两种方法】
①通过oracle提供的向导工具;dbca【数据库配置助手】
②可以用手工步骤直接创建。
【学生表科目分数按科目分组按分数降序取前三条查询【3者之间是有一定区别的】】
select * from(select subject,score,row_number() over(partition by subject order by score desc ) 成绩排名 from test) temp where temp.成绩排名<=3;
select * from(select subject,score,dense_rank() over(partition by subject order by score desc ) 成绩排名 from test) temp where temp.成绩排名<=3;
select * from(select subject,score,rank() over(partition by subject order by score desc ) 成绩排名 from test) temp where temp.成绩排名<=3;