首页 技术 正文
技术 2022年11月21日
0 收藏 847 点赞 3,277 浏览 8686 个字

高级查询

1.关联查询

作用:可以跨多表查询

–查询出员工的名字和他所在部门的名字

//错误
//select first_name,name from s_emp,s_dept;

//错误原因:
产生了笛卡尔积(两张表中的数据每条记录都进行匹配),
导致查询结果中出现了很多冗余的结果,所以,为了避免
笛卡尔积,我们应该采用where字句对查询结果进行过滤.

//正确
select first_name,name from s_emp,s_dept
where s_dept.id = s_emp.dept_id;

Oracle中可以给列取别名,还可以给表取别名,甚至可以给查询结果取别名,
可以把上述语句改造成:

//传统写法:
select e.first_name,d.name from s_emp e,s_dept d
where e.dept_id = d.id;

//新写法:
select e.first_name,d.name from s_emp e
join s_dept d on e.dept_id = d.id;

练习:

–查询出部门名以及它所在的区域名称
select d.name 部门名,r.name 区域名 from s_dept d join s_region r
on d.region_id=r.id;

–查询出’Sales’部门的所有员工的名字和工资
select e.first_name,e.salary,d.name from s_emp e join s_dept d
on e.dept_id=d.id where d.name=’Sales’;

–查询出设在Asia的部门名
select d.name,r.name from s_dept d join s_region r
on d.region_id=r.id where r.name=’Asia’;

–查询出名字叫Unisports的客户订单的信息
select c.name,o.* from s_customer c join s_ord o
on o.customer_id=c.id where c.name=’Unisports’;

–查询出设在Asia工作的员工名,工资,职称
select e.first_name,e.salary,e.title,r.name from s_emp e
join s_dept d on e.dept_id=d.id
join s_region r on d.region_id=r.id
where r.name=’Asia’;

–查询出客户名及它的订单号,总费用
select c.name,o.id,o.total from s_customer c left join s_ord o
on o.customer_id=c.id;

–查询订单号,订单费用以及该订单所对应的客户名
select o.id,o.total,c.name from s_ord o left join s_customer c
on o.customer_id=c.id;

select o.id,o.total,c.name from s_customer c right join s_ord o
on o.customer_id=c.id;

我们的关联查询分为2大类:
1.内联查询
[inner] join

2.外联查询
a.左外联:以关联点(join)左边的表为基准,非基准表中没有数据与
基准表中匹配,则基准表中的行记录还是会被显示.
left [outer] join

b.右外联:以关联点(join)右边的表为基准,非基准表中没有数据与
基准表中匹配,则基准表中的行记录还是会被显示.
right [outer] join

注意:A left join B == B right join A

c.全外联
full [outer] join

d.交叉联:返回连接两张表格的笛卡尔积
cross [outer] join

自关联查询:同一张表自己关联自己
–找出员工名以及他的上司名
select e.first_name 员工名,m.first_name 上司名 from s_emp e join s_emp m
on e.manager_id=m.id;

练习:

–查询出在’Asia’工作的员工
select e.*,r.name from s_emp e
join s_dept d on e.dept_id=d.id
join s_region r on d.region_id=r.id
where r.name=’Asia’;

–找出Womansport所购买的订单信息(订单编号,费用,支付方式)
select c.name,o.id,o.total,o.payment_type from s_customer c
left join s_ord o on o.customer_id=c.id where c.name=’Womansport’;

–找出Operations部门工作的员工名,工资,并且按照工资降序排列
select e.first_name,e.salary,d.name from s_emp e
join s_dept d on e.dept_id=d.id
where d.name=’Operations’
order by 2 desc;
———————————————————-

2.分组查询

定义:利用内置的分组函数来查询

Oracle数据库中提供了相对应的分组函数来支持分组查询:
sum()求总和,会自动忽略null值
count()求总个数,包含null值和相同值
avg()求平均数,会自动忽略null值
max()求最大值
min()求最小值

注意:组函数也叫做多行函数,与单行函数不同的是,组函数可以
同时处理多行数据.

分组的语法:
select 列名 [列别名],组函数(列名) from 表名
where 字句
group by 列名
having 字句
order by 列;

–查询出全公司的最高工资,最低工资,平均工资和工资总和
select max(salary),min(salary),avg(salary),sum(salary) from s_emp;

–查询出各个部门的最高工资,最低工资,平均工资和工资总和
select dept_id,max(salary),min(salary),avg(salary),sum(salary) from s_emp
group by dept_id;

–查询出41,42,50部门的最高工资,最低工资,平均工资和工资总和
select dept_id,max(salary),min(salary),avg(salary),sum(salary) from s_emp
where dept_id in(41,42,50) group by dept_id;

where和having的差别
1.where是条件过滤,是在分组之前的过滤,不能使用组函数.
2.having是在分组之后的进一步过滤,可以使用组函数.

注意:
出现在group by后面的列,才能出现select后面,除非它被组函数修饰!!!

练习:
–查询出各个区域名和设在此区域的部门数量
select r.id,r.name,count(d.id) from s_region r left join s_dept d
on d.region_id=r.id group by r.id,r.name;

–查询出客户名及客户的订单数
select c.name,count(o.id) from s_customer c left join s_ord o
on o.customer_id=c.id group by c.name;

–查询出订单数超过一个的客户
select c.id,c.name,c.phone,count(o.id) from s_customer c left join s_ord o
on o.customer_id=c.id group by c.id,c.name,c.phone having count(o.id)>1;

–查询出平均工资超过1300的部门编号
select dept_id,avg(salary) from s_emp group by dept_id
having avg(salary)>1300;

–统计本公司的员工数
select count(*) from s_emp;

–统计本公司的职称个数
select count(*) from s_title;
select count(distinct title) from s_emp;

–统计各个部门的员工数,按照员工数降序排列
select e.dept_id,count(*) from s_emp e group by e.dept_id order by 2 desc;

select d.id,d.name,count(*) from s_emp e join s_dept d
on e.dept_id=d.id group by d.id,d.name order by 3 desc;

–查询出各个区域及本区域工作的员工数,并且按照员工数降序排列
select r.id,r.name,count(*) from s_emp e
join s_dept d on e.dept_id=d.id
join s_region r on d.region_id=r.id
group by r.id,r.name
order by 3 desc;

–查询出各职称的员工数量
select title,count(*) from s_emp group by title;

–查询出工资超过1200的各部门员工数量
select dept_id,count(*) from s_emp where salary>1200 group by dept_id;

–查询出人数超过3个员工的部门编号和部门名称
select d.id,d.name,count(*) from s_dept d join s_emp e
on e.dept_id=d.id group by d.id,d.name having count(*)>3;

———————————————————–

3.子查询

定义:查询中嵌套查询就是子查询

注意:子查询必须用()括起来

子查询的本质:
a.内联视图
b.把子查询的结果作为外部查询的条件

–找出工资大于Mark的员工名字和工资
//1.查询出Mark的工资是多少?
select salary from s_emp where first_name=’Mark’;//1450
//2.以第一个查询的结果作为条件查询出最终结果
select * from s_emp where salary > 1450;

==>整合成子查询:
select * from s_emp where salary>
(select salary from s_emp where first_name=’Mark’);

–找出平均工资大于公司平均工资的部门编号
//1.公司平均工资
select avg(salary) from s_emp;//1255.08
//2.以第一个查询的结果作为条件查询出最终结果
select dept_id,avg(salary) from s_emp group by dept_id
having avg(salary)>1255.08;

==>整合成子查询:
select dept_id,avg(salary) from s_emp group by dept_id
having avg(salary)>(select avg(salary) from s_emp);

–找出与’Ben’同部门的员工
//1.查询出’Ben’所在的部门编号
select dept_id from s_emp where first_name=’Ben’;//43

//2.查询出部门编号为第一个查询结果的所有员工,并且把’Ben’去除
select * from s_emp where dept_id=43 and first_name<>’Ben’;

==>整合成子查询:
select * from s_emp where dept_id=
(select dept_id from s_emp where first_name=’Ben’)
and first_name<>’Ben’;

–查询出客户名,电话号码,以及订单数

//分组+关联
select c.name,c.phone,count(o.id) from s_customer c left join s_ord o
on o.customer_id=c.id group by c.name,c.phone;

//子查询完成
//相关子查询
select c.name,c.phone,
(select count(o.id) from s_ord o where o.customer_id=c.id)
from s_customer c

//无关子查询
select c.name,c.phone,a.sum from s_customer c join
(select c.id id,count(o.id) sum from s_customer c left join s_ord o
on o.customer_id=c.id group by c.id) a on a.id=c.id;

子查询的分类:
1.无关子查询:
内查询没有用到外查询的列,而且内查询可以单独运行.

2.相关子查询:
内查询使用了外查询的列,而且内查询不能单独运行.

子查询的特点:
1.子查询很灵活,可以解决很多其他查询方式不能解决的问题
2.子查询效率很低,其中相关子查询效率最低
3.子查询嵌套的层数越多,则效率越低

为什么相关子查询的效率极其低下?
内查询用到了外查询的列,每次查询行记录时都会迭代表格中
每一行的行记录,而这种迭代中产生的值都是动态生成的.

结论:
如果可以使用分组查询就不要使用子查询
如果一定要用子查询,则优先使用无关子查询,实在没有办法最后
选择相关子查询.

性能排序:
分组/关联查询>无关子查询>相关子查询

–找出各个部门中大于他所在部门平均工资的员工名和工资
//相关
select e.first_name,e.salary from s_emp e where e.salary>
(select avg(salary) from s_emp e1 where e1.dept_id=e.dept_id);

//无关
select e.first_name,e.salary from s_emp e join
(select dept_id,avg(salary) avg from s_emp group by dept_id) a
on a.dept_id=e.dept_id where e.salary>a.avg;

–找出职称相同的员工
select first_name,title from s_emp where title in
(select title from s_emp group by title having count(*)>=2);

——————————————————————

rownum:

特点:永远从1开始,依次递增,从不产生间隔

select rownum,e.* from s_emp e;
select rownum,e.* from s_emp e where rownum = 1;
select rownum,e.* from s_emp e where rownum = 5;
select rownum,e.* from s_emp e where rownum <= 5;
select rownum,e.* from s_emp e where rownum >= 5;

rownum可以解决的问题:
1.top_N问题

解决思路:
1.利用子查询,先排序,后过滤
2.利用rownum的特性来直接取最前面几行的记录

–查询本公司工资前三的员工
select * from
(select first_name,salary from s_emp order by 2 desc)
where rownum <= 3;

–查询出订单价格最低的两个现金支付的订单
select * from
(select o.id,o.total,o.payment_type from s_ord o where o.payment_type=’CASH’
order by 2) where rownum<=2;

2.分页问题
通项公式:
select outer_.* from
(
select rownum rownum_,core_.* from
(
select 列 from 表 where 条件 order by 字句;–核心业务
)
core_ where rownum<=endvalue
)
outer_ where outer_.rownum_>=startvalue;

–查询员工表第6到第10行记录
select outer_.* from
(
select rownum rownum_,core_.* from
(
select * from s_emp
)
core_ where rownum<=10
)
outer_ where outer_.rownum_>=6;

select outer_.* from
(select rownum rownum_,e.* from s_emp e where rownum<=10)
outer_ where outer_.rownum_>=6;

–找出在Asia工作的员工的第2行到第4行记录
select outer_.* from
(
select rownum rownum_,core_.* from
(
select * from s_emp e
join s_dept d on e.dept_id=d.id
join s_region r on d.region_id=r.id
where r.name=’Asia’
)
core_ where rownum<=4
)
outer_ where outer_.rownum_>=2;

select a.* from
(
select rownum rownum_,first_name,salary from
(
select first_name,salary from s_emp where dept_id in
(
select id from s_dept where region_id=
(
select id from s_region where name=’Asia’
)
)
)
)
a where a.rownum_>=2 and a.rownum_<=4;

———————————————————

集合操作

如:t_test
idname
1jack
2rose
3tom
4mary

MINUS求两个结果集的差
select * from t_test where id=1 or id=3
minus
select * from t_test where id>=3;

INTERSECT求两个结果集的交集
select * from t_test where id=1 or id=3
intersect
select * from t_test where id>=3;

UNION求两个结果集的并集(不包含重复结果)
select * from t_test where id=1 or id=3
union
select * from t_test where id>=3;

UNION ALL求两个结果集的并集(包含重复记录)
select * from t_test where id=1 or id=3
union all
select * from t_test where id>=3;

———————————————————

exists和not exists

在子查询中,使用在where字句,它只关心条件是否有存在的可能,
如果有可能,则返回true,反之则返回false
not exists与exists正好相反

–找出与’Ben’同部门的员工
select e.first_name,e.dept_id from s_emp e
where exists
(select 1 from s_emp e1 where e1.dept_id=e.dept_id
and e1.first_name=’Ben’)
and e.first_name <> ‘Ben’;

–找出各个部门工资排名前二的员工
解题思路:本部门中比’我’工资高的员工不超过一个
select e.dept_id,e.first_name,e.salary from s_emp e
where exists
(select 1 from s_emp e1 where e1.dept_id=e.dept_id and
e1.salary>e.salary having count(*)<=1)
order by 1;

select e.dept_id,e.first_name,e.salary from s_emp e
where not exists
(select 1 from s_emp e1 where e1.dept_id=e.dept_id and
e1.salary>e.salary having count(*)>1)
order by 1;

–找出各个部门工资最高的员工
解题思路:本部门中比’我’工资高的人没有
select e.dept_id,e.first_name,e.salary from s_emp e
where not exists
(select 1 from s_emp e1 where e1.dept_id=e.dept_id and
e1.salary>e.salary)
order by 1;

———————————————————

其他运算符:

1.=any

–找出与41部门工资相同的其他部门的员工

2.all
–找出工资比41部门任何一个人都高的员工

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,000
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,512
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,358
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,141
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,771
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,849