--Oracle开发中常用sql
--子查询
嵌套在其他sql中的一条查询语句,该查询语句就是子查询。
当我们执行的sql语句需要先从数据库中获取一些数据才能
运行时,那么先期执行的这条sql就是子查询,是为了给要
实际执行的sql提供数据的。
查看工资高于CLARK的员工?
select ename, sal
from emp
where sal > (select sal from emp where ename = 'CLARK');
查看与ALLEN同职位的员工?
select * from emp where job = (select job from emp where ename = 'ALLEN');
子查询常用于查询语句,但是亦可以在DDL,dml中使用。
DDL中使用,例如:
基于一个查询结果集快速创建一张表。
create table myemp
as
select e.empno,e.ename,e.sal,e.job,
e.deptno,d.dname,d.loc
from emp e,dept d
where e.deptno =d.deptno;
desc myemp;
select * from myemp;
dml中使用子查询
删除CLARK所在部门的所有员工
delete from myemp
where deptno = (select deptno from myemp where ename = 'CLARK');
子查询根据查询结果分为:
单行单列子查询,多行单列子查询,
多行多列子查询
其中单列的子查询多用在 where 子句中做过滤条件。
而多行多列子查询通常用于 from 中当做表看待。
select ename,job from emp;
查看谁比公司平均工资高?
select ename, sal from emp where sal > (select avg(sal) from emp);
查看与职位是“SALESMAN”相同部门的
其他职位员工?
select ename, job, deptno
from emp
where deptno in (select deptno from emp where job = 'SALESMAN')
and job <> 'SALESMAN';
查看比20与30号部门工资高的员工信息?
select *
from emp
where sal > all (select sal from emp where deptno in (20, 30));
--等价
select *
from emp
where sal > (select max(sal) from emp where deptno in (20, 30))
exists关键字
exists是用于where中作为判断条件使用的
其后需要紧跟一个子查询,只要该子查询能查询出
至少一条记录,那么exists表达式就返回真,
也可以使用 not exists 来表达相反的效果。
查看所以员工的部门信息
select deptno, dname
from dept d
where exists (select * from emp e where e.deptno = d.deptno);
查看每个部门的最低薪水,前提是
该部门的最低薪水要高于30号部门的最低薪水?
select deptno, min(sal)
from emp
group by deptno
having min(sal) > (select min(sal) from emp where deptno = 30);
查看谁比自己所在部门平均工资高?
select e.ename,e.sal,e.deptno
from emp e, (select avg(sal) avg_sal, deptno from emp group by deptno) s
where e.deptno = s.deptno
and e.sal > s.avg_sal;
子查询也可以应用在select子句中
可以实现外连接的效果
查看每个员工以及所在部门名称信息:
select e.ename, (select d.dname from dept d where d.deptno = e.deptno)
from emp e;
--分页查询
当查询的数据量过度时,会导致一些情况:
1.服务端响应慢
2.系统资源占用多
3.数据过剩
为了解决这些问题,通常我们会分批查询数据
这个过程就是分页查询。
由于分页查询没有标准的sql语法,所以不同
数据库对于分页的机制不一致(方言)
select rownum,ename, sal, job, deptno from emp;
Oracle支持一个关键字rownum
rownum是一个伪列,该列不存在于
任何一张表中,但是每张表都可以查询该列。
而该列在结果集的值是结果集中每条记录的“行号”
rownum给结果集编号是在查询的过程中进行的,只要可以
从表中查询出一条记录,该记录的行号就会作为这条记录
rownum字段的值,rownum从1开始递增。
由于rownum从1开始,所以在第一次查询表中数据进行编号时。
不要使用rownum做大于1以上的数字判断,否则查询不到数据:
select rownum,ename,sal from emp where rownum >1;
select *
from (select rownum rn, ename, sal from emp)
where rn between 5 and 10;
查看公司工资排名的第6-10名
select *
from (select rownum rn, t.*
from (select ename, sal from emp order by sal desc) t)
where rn between 6 and 10;
下面的效率好,不需要的数据就不编号了
select *
from( select rownum rn,t.*
from (select ename,sal from emp order by sal desc) t
where rownum <=10
)
where rn >= 6;
计算分页公式:
页数:page
每页显示的条数:pageSize
start = (page-1)*pageSize+1--[当前页之前条数+1]
end = pageSize*page
一页显示5条,显示第2页
decode 函数,可以实现类似java中的分支操作:
select ename,
job,
sal,
decode(job,
'MANAGER',
sal * 1.2,
'ANALYST',
sal * 1.2,
'SALESMAN',
sal * 1.05,
sal) bonus
from emp;
select count(*), job from emp group by job;
在group by中使用decode可以做到
将字段值不同的记录看做一个大组,只要
将需要看做一组的记录中该字段的值替换为相同的值即可。
select decode(
job,
'MANAGER','VIP',
'ANALYST','VIP',
'OTHER'
),count(*)
from emp
group by decode(
job,
'MANAGER','VIP',
'ANALYST','VIP',
'OTHER'
);
select deptno,dname,loc
from dept
order by decode(
dname,
'OPERATIONS',1,
'ACCOUNTING',2,
'SALES',3
);
排序函数:
排序函数可以按照指定的字段分组,然后再按照
指定的字段排序,最后为记录生成组内的编号。
1:row_number函数,生成组内连续且唯一的数字。--[独立编号]
查看每个部门中工资的排名:
select ename,
sal,
deptno,
row_number() over(partition by deptno order by sal desc) rank
from emp;
2:rank函数:生成组内不连续不唯一的数字,--[跳跃并列]
select
ename,sal,deptno,
rank() over(
partition by deptno
order by sal desc
) rank
from emp;
3:dense_rank()生成组内连续但不唯一的数字--[不跳跃并列]
select ename,
sal,
deptno,
dense_rank() over(partition by deptno order by sal desc) rank
from emp;
--集合运算
select ename,job,sal
from emp where job = 'MANAGER'
--union
--intersect
minus
select ename,job,sal
from emp where sal >2500;
--下面的是创建一千行数据的表
CREATE TABLE sales_tab (
year_id NUMBER NOT NULL,
month_id NUMBER NOT NULL,
day_id NUMBER NOT NULL,
sales_value NUMBER(10,2) NOT NULL
);
INSERT INTO sales_tab
SELECT TRUNC(DBMS_RANDOM.value(2010, 2012)) AS year_id,
TRUNC(DBMS_RANDOM.value(1, 13)) AS month_id,
TRUNC(DBMS_RANDOM.value(1, 32)) AS day_id,
ROUND(DBMS_RANDOM.value(1, 100), 2) AS sales_value
FROM dual
CONNECT BY level <= 1000;
SELECT * FROM sales_tab
ORDER BY year_id,month_id,day_id
查看每天的营业额?
select year_id, month_id, day_id, sum(sales_value)
from sales_tab
group by year_id, month_id, day_id
order by year_id, month_id, day_id;
查看每月的营业额?
select year_id, month_id, sum(sales_value)
from sales_tab
group by year_id, month_id
order by year_id, month_id;
查看每年的营业额?
select year_id, sum(sales_value)
from sales_tab
group by year_id
order by year_id;
查看全部的营业额?
select sum(sales_value) from sales_tab;
--高级分组函数
group by rollup (a,b,c)
等价于:
group by a,b,c
union all
group by a,b
union all
group by a
union all
全表
查看每天,每月,每年,以及全部
营业额的统计?
select year_id, month_id, day_id, sum(sales_value)
from sales_tab
group by rollup(year_id, month_id, day_id)
order by year_id, month_id, day_id;
cube函数:
cube会将每个参数的不同组合进行分组
然后将所有分组统计结果并在一起。
分组次数是2的参数个数次方。
group by cube(a,b,c)
abc,
ab,
ac,
bc,
a,
b,
c
全表
select year_id, month_id, day_id, sum(sales_value)
from sales_tab
group by cube(year_id, month_id, day_id)
order by year_id, month_id, day_id;
grouping sets()
该函数可以按照指定的分组方式进行分组,
然后将结果集并在一起。
其中每一个参数就是一种组合方式。
查看每天以及每月的营业额?
select year_id, month_id, day_id, sum(sales_value)
from sales_tab
group by grouping sets((year_id, month_id, day_id),(year_id, month_id))
order by year_id, month_id, day_id;