Oracle学习日历(三)-表查询

oracle表基本查询
介绍

在我们讲解的过程中我们利用scott用户存在的几张表(emp,dept)为大家演示如何使用select语句,select语句在软件编程中非常有用,希望大家好好的掌握。

Clear 清屏命令

 

公司员工表常用列名


emp 雇员表


clerk 普员工
salesman 销售
manager  经理
analyst 分析师
president  总裁
mgr  上级的编号
hiredate 入职时间
sal 月工资
comm 奖金
deptno 部门
dept部门表
deptno 部门编号
accounting 财务部
research  研发部
operations 业务部
loc 部门所在地点
salgrade   工资级别
grade    级别
losal    最低工资
hisal    最高工资

简单的查询语句
查看表结构(可以在command窗口执行,PL/SQL的SQL窗口会报错)

DESC emp;

查询列的语句

查询所有列

SELECT * FROM dept;

查询某个列

Select ename from emp;

查询多个列

Select ename,sal,job,deptno from emp;

切忌动不动就用select *
SET TIMING ON; 打开显示操作时间的开关,显示查询所用的时间。

CREATE TABLE users(userId VARCHAR2(10), uName VARCHAR2 (20), uPassw VARCHAR2(30));
INSERT INTO users VALUES('a0001', '啊啊啊啊', 'aaaaaaaaaaaaaaaaaaaaaaa');
--从自己复制,加大数据量 大概几万行就可以了  可以用来测试sql语句执行效率
INSERT INTO users (userId,UNAME,UPASSW) SELECT * FROM users;
-- 统计一张表共有多少行数
SELECT COUNT (*) FROM users; 

 如何取消重复行DISTINCT

SELECT DISTINCT deptno, job FROM emp;

查询SMITH所在部门,工作,薪水

SELECT deptno,job,sal FROM emp WHERE ename = 'SMITH';

注意:oracle对‘内容’的大小写是区分的,所以ename='SMITH'和ename='smith'是不同的
 

 使用算术表达式 nvl  null


问题:如何显示每个雇员的年工资?

Select sal*12,eanme from emp;

查询时使用别名

Select sal*12 "年工资",ename "姓名" FROM emp;

如何处理null值,使用nvl函数来处理

查询年工资,姓名,奖金,(年工资包含了一年所有的奖金如果奖金中有null值,则查询不全,为避免空值则需要使用nvl函数来处理)。

SELECT sal*12+nvl(comm, 0)*12 "年工资" , ename, comm FROM emp;

 使用where子句
问题:如何显示工资高于3000的 员工?

SELECT * FROM emp WHERE sal > 3000;

问题:如何查找1982.1.1后入职的员工?

SELECT ename,hiredate FROM emp WHERE hiredate >'1-1月-1982';

问题:如何显示工资在2000到3000的员工?

SELECT ename,sal FROM emp WHERE sal >=2000 AND sal <= 3000;

 如何连接字符串(||)

 SELECT ename|| ' is a ' || job FROM emp;

如何使用like操作符
%:表示0到多个字符  _:表示任意单个字符
问题:如何显示首字符为S的员工姓名和工资?

 SELECT ename|| ' is a ' || job FROM emp;

如何显示第三个字符为大写O的所有员工的姓名和工资?下划线表示一个字符

SELECT ename,sal FROM emp WHERE ename like '__O%';

在where条件中使用in

问题:如何显示empno为7844, 7839,123,456 的雇员情况?

SELECT * FROM emp WHERE empno in (7844, 7839,123,456);

 使用is null的操作符

问题:如何显示没有上级的雇员的情况?
错误写法:select * from emp where mgr = '';
正确写法:

SELECT * FROM emp WHERE mgr is null;

使用逻辑操作符号


问题:查询工资高于500或者是岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J?

SELECT * FROM emp WHERE (sal >500 or job = 'MANAGER') and ename LIKE 'J%';

使用order by  字句   默认asc 升序 desc降序


问题:如何按照工资的从低到高的顺序显示雇员的信息?

SELECT * FROM emp ORDER by sal;

问题:按照部门号升序而雇员的工资降序排列

SELECT * FROM emp ORDER by deptno asc, sal DESC;

使用列的别名排序

问题:按年薪排序

select ename, (sal+nvl(comm,0))*12 "年薪" from emp order by "年薪" asc;


别名需要使用“”号圈中,英文不需要“”号

 分页查询
等学了子查询再说吧。。。。。。。。

Clear 清屏命令
 


oracle表复杂查询


 说明
在实际应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,现在我们给大家介绍较为复杂的select语句
 

数据分组

 

max(最大),min(最小), avg(平均), sum(总和), count(计数)
问题:如何显示所有员工中最高工资和最低工资?

SELECT MAX(sal),min(sal) FROM emp ;

      最高工资那个人是谁?
错误写法:

select ename, sal from emp where sal=max(sal);

正确写法:

select ename, sal from emp where sal=(select max(sal) from emp);

注意:select ename, max(sal) from emp;这语句执行的时候会报错,说ORA-00937:非单组分组函数。因为max是分组函数,而ename不是分组函数.......
但是select min(sal), max(sal) from emp;这句是可以执行的。因为min和max都是分组函数,就是说:如果列里面有一个分组函数,其它的都必须是分组函数,否则就出错。这是语法规定的

 

问题:如何显示所有员工的平均工资和工资总和?

Select avg(sal),sum(sal) from emp;

问题:如何计算总共有多少员工

Select count(ename) from emp;

Select count(*) from emp;

扩展要求:
查询最高工资员工的名字,工作岗位

SELECT ename, job, sal FROM emp  where sal = (SELECT MAX(sal) FROM emp);

显示工资高于平均工资的员工信息

SELECT * FROM emp  where sal > (SELECT AVG(sal) FROM emp);

把所有低于平均工资的员工工资叫100元

Update emp set sal=sal+100 where sal<(select avg(sal) from emp);

group by 和 having子句


group by用于对查询的结果分组统计,
having子句用于限制分组显示结果。

问题:如何显示每个部门的平均工资和最高工资?

SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno;

(注意:这里暗藏了一点,如果你要分组查询的话,分组的字段deptno一定要出现在查询的列表里面,否则会报错。因为分组的字段都不出现的话,就没办法分组了)
 

问题:显示每个部门的每种岗位的平均工资和最低工资?

SELECT min(sal), AVG(sal), deptno, job FROM emp GROUP by deptno, job;

问题:显示平均工资低于2000的部门号和它的平均工资?

SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno having AVG(sal) < 2000;

 对数据分组的总结


1 分组函数只能出现在选择列表、having、order by子句中(不能出现在where中)
2 如果在select语句中同时包含有group by, having, order by 那么它们的顺序是group by, having, order by

如:

SELECT deptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) < 2000 orader by avg(sal);

3 在选择列中如果有列、表达式和分组函数,那么这些列和表达式必须有一个出现在group by 子句中,否则就会出错。

SELECT deptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) < 2000;

这里deptno就一定要出现在group by 中



多表查询


说明
多表查询是指基于两个和两个以上的表或是视图的查询。在实际应用中,查询单个表可能不能满足你的需求,(如显示sales部门位置和其员工的姓名),这种情况下需要使用到(dept表和emp表)

问题:显示雇员名,雇员工资及所在部门的名字【笛卡尔集】?
规定:多表查询的条件是至少不能少于表的个数-1才能排除笛卡尔集
(如果有N张表联合查询,必须得有N-1个条件,才能避免笛卡尔集合)

SELECT a1.ename, a1.sal, a2.dname FROM emp a1, dept a2 WHERE a1.deptno = a2.deptno;

问题:显示部门号为10的部门名、员工名和工资?

SELECT d.dname, e.ename, e.sal FROM emp e, dept d WHERE e.deptno = d.deptno and e.deptno = 10;

问题:显示各个员工的姓名,工资及工资的级别?
先看salgrade的表结构和记录

select * from salgrade;
    GRADE         LOSAL          HISAL
-------------   -------------   ------------
        1          700           1200
        2          1201          1400
        3          1401          2000
        4          2001          3000
        5          3001          9999
SELECT e.ename, e.sal, s.grade FROM emp e, salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;

注意:求之间的数要用到 BETWEEN

扩展要求:
问题:显示雇员名,雇员工资及所在部门的名字,并按部门排序?

SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno ORDER by e.deptno;

(注意:如果用group by,一定要把e.deptno放到查询列里面)



自连接


自连接是指在同一张表的连接查询
问题:显示某个员工的上级领导的姓名?
比如显示员工‘FORD’的上级

SELECT worker.ename, boss.ename FROM emp worker,emp boss WHERE worker.mgr = boss.empno AND worker.ename = 'FORD';

子查询


什么是子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
单行子查询
单行子查询是指只返回一行数据的子查询语句
请思考:显示与SMITH同部门的所有员工?
思路:
1 查询出SMITH的部门号

select deptno from emp WHERE ename = 'SMITH';

2 显示

SELECT * FROM emp WHERE deptno = (select deptno from emp WHERE ename = 'SMITH');

数据库在执行sql 是从左到右扫描的, 如果有括号的话,括号里面的先被优先执行。
 

多行子查询 DISTINCT all any


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

请思考:如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号

SELECT DISTINCT job FROM emp WHERE deptno = 10;
SELECT * FROM emp WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10);

(注意:不能用job=..,因为等号=是一对一的)

 在多行子查询中使用all操作符
问题:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号?

SELECT ename, sal, deptno FROM emp WHERE sal > all (SELECT sal FROM emp WHERE deptno = 30);

扩展要求:
大家想想还有没有别的查询方法。

SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30);

执行效率上, 函数高得多

在多行子查询中使用any操作符
问题:如何显示工资比部门30的任意一个员工的工资高的员工姓名、工资和部门号?

SELECT ename, sal, deptno FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30);

扩展要求:
大家想想还有没有别的查询方法。

SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT min(sal) FROM emp WHERE deptno = 30);

多列子查询

单行子查询是指子查询只返回单列、单行数据,多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询是指查询返回多个列数据的子查询语句。

请思考如何查询与SMITH的部门和岗位完全相同的所有雇员。

SELECT deptno, job FROM emp WHERE ename = 'SMITH';
SELECT * FROM emp WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH');

注意:(deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH');

前面的括号里面的 deptno要对应后面括号里面的deptino,前面括号里面的job要对应后面括号里面的job.
 

在from子句中使用子查询


请思考:如何显示高于自己部门平均工资的员工的信息
思路:
1. 查出各个部门的平均工资和部门号

SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno;

查询结果

DEPTNO      MYSAL

  ------        ----------

    30       1566.66666

    20           2175

10        2916.66666
2. 把上面的查询结果看做是一张子表

SELECT e.ename, e.deptno, e.sal, ds.mysal 
FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) ds 
WHERE e.deptno = ds.deptno AND e.sal > ds.mysal;

如何衡量一个程序员的水平?
网络处理能力, 数据库, 程序代码的优化程序的效率要很高

小总结:
在这里需要说明的当在from子句中使用子查询时,该子查询会被作为一个视图来对待,因此叫做内嵌视图,当在from子句中使用子查询时,必须给子查询指定别名。
注意:别名不能用as,如:

SELECT e.ename, e.deptno, e.sal, ds.mysal 
FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) as ds 
WHERE e.deptno = ds.deptno 
AND e.sal > ds.mysal;


在ds前不能加as,否则会报错  (给表取别名的时候,不能加as;但是给列取别名,是可以加as的)
 

分页查询


按雇员的id号升序取出
oracle的分页一共有三种方式

1.根据rowid来分
 

select * from t_xiaoxi 
where rowid in (select rid from 
                        (select rownum rn, rid from(
                                select rowid rid, cid 
                                from t_xiaoxi 
                                order by cid desc)
                         where rownum<10000)
                 where rn>9980) 
order by cid desc;


执行时间0.03秒
2.按分析函数来分

select * from (
                select t.*, row_number() over(order by cid desc) rk 
                from t_xiaoxi t) 
where rk<10000 
and rk>9980;


执行时间1.01秒
3.按rownum来分

select * from (
            select t.*,rownum rn 
            from (select * from t_xiaoxi order by cid desc)t 
            where rownum<10000) 
where rn>9980;


执行时间0.1秒

其中t_xiaoxi为表名称,cid为表的关键字段,取按cid降序排序后的第9981-9999条记录,t_xiaoxi表有70000多条记录。
个人感觉1的效率最好,3次之,2最差。

//测试通过的分页查询okokok

select * from (
        select a1.*, rownum rn 
        from (select ename,job from emp) a1 
        where rownum<=10)
where rn>=5;


 

Rownum分页查询


1. rownum 分页

SELECT * FROM emp;

2. 显示rownum[oracle分配的]

SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e;

e.*  表示把子查询(SELECT * FROM emp) 重新取出来。
Rownum  rn相当于Oracle分配的行的ID号  
3.挑选出6—10条记录
先查出1-10条记录

SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM <= 10;

如果后面加上rownum>=6是不行的, 在一个子查询里面rownum只能用一次.
4. 然后查出6-10条记录

SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM <= 10) WHERE rn >= 6;

几个查询变化
a. 指定查询列,只需要修改最里层的子查询
只查询雇员的编号和工资

SELECT * FROM (
        SELECT e.*, ROWNUM rn 
        FROM (SELECT ename, sal FROM emp) e 
        WHERE ROWNUM <= 10) 
WHERE rn >= 6;

排序查询,只需要修改最里层的子查询
工资排序后查询6-10条数据

SELECT * FROM (
        SELECT e.*, ROWNUM rn 
        FROM (SELECT ename, sal FROM emp ORDER by sal) e 
        WHERE ROWNUM <= 10) 
WHERE rn >= 6;

查询结果创建新表


这个命令是一种快捷的建表方式

CREATE TABLE mytable (id, name, sal, job, deptno) 
as SELECT empno, ename, sal, job, deptno FROM emp;

创建好之后,desc mytable;和select * from mytable;看看结果如何?
 

合并查询


有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号union,union all,intersect,minus
多用于数据量比较大的数据局库,运行速度快。


1). union

 

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。

SELECT ename, sal, job FROM emp WHERE sal >2500
UNION
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER';

2).union all


该操作符与union相似,但是它不会取消重复行,而且不会排序。

SELECT ename, sal, job FROM emp WHERE sal >2500
UNION ALL
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER';

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。


3). intersect


  使用该操作符用于取得两个结果集的交集。

SELECT ename, sal, job FROM emp WHERE sal >2500
INTERSECT
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER';

4). minus


使用改操作符用于取得两个结果集的差集,他只会显示存在第一个集合中,而不存在第二个集合中的数据。

SELECT ename, sal, job FROM emp WHERE sal >2500
MINUS
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER';


(MINUS就是减法的意思)
 

创建数据库有两种方法


1). 通过oracle提供的向导工具。
   database Configuration Assistant  【数据库配置助手】
2).我们可以用手工步骤直接创建。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值