高级查询

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
id name
1 jack
2 rose
3 tom
4 mary

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部门任何一个人都高的员工

Oracle笔记3-高级查询的更多相关文章

  1. Oracle笔记 多表查询

    Oracle笔记  多表查询   本次预计讲解的知识点 1. 多表查询的操作.限制.笛卡尔积的问题: 2. 统计函数及分组统计的操作: 3. 子查询的操作,并且结合限定查询.数据排序.多表查询.统计查 ...

  2. 6.5笔记-DQL高级查询

    一.高级查询 Exists Drop table if exists result; 子查询有返回结果: EXISTS子查询结果为TRUE 子查询无返回结果: EXISTS子查询结果为FALSE, 外 ...

  3. Oracle数据库——SQL高级查询

    一.涉及内容 1.掌握SELECT语句的多表连接查询. 2.掌握SELECT语句的子查询. 二.具体操作 (一)根据Oracle数据库scott方案下的emp表和dept表,完成下列操作: 1.查询所 ...

  4. oracle笔记2-多表查询和子查询

    --查询出当前用户下的所有表 select table_name from user_tables; --执行顺序原则:  from  where group by  having   select  ...

  5. Oracle查询优化改写--------------------高级查询

    一.给结果集分页 二.重新生成房间号 三.跳过表中n行 四.排列组合去重

  6. Oracle学习笔记(7)——高级查询(1)

    在学习高级查询之前,我们先了解一下怎样查看Oracle数据库中的全部表.由于我们要使用到Oracle数据库中SCOTT用户下的几张表(这些表是Oracle数据库自带的表). 分组查询 分组函数的概念: ...

  7. oracle学习笔记(十二) 查询练习(二) 高级查询

    高级查询练习 /*--------------------------------------------- 分组查询 -------------------------------------*/ ...

  8. oracle学习笔记(十一) 高级查询

    高级查询 分组查询 select * from student [where ] [having ] --二次限定 [order by] --asc升序 desc降序 默认升序 查看EMPLOYEE表 ...

  9. Oracle笔记(1) 简单查询、限定查询、数据的排序

    Oracle笔记(四) 简单查询.限定查询.数据的排序   一.简单查询 SQL(Structured Query Language) 结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及 ...

随机推荐

  1. Adapter 代码中启动报错

    安装好Adapter之后,在designer中可以启动Adapter,但在代码中启动却总是报错,“could not create RVMQSession"或者是“native implem ...

  2. Bootstrap <基础二十二>超大屏幕(Jumbotron)

    Bootstrap 支持的另一个特性,超大屏幕(Jumbotron).顾名思义该组件可以增加标题的大小,并为登陆页面内容添加更多的外边距(margin).使用超大屏幕(Jumbotron)的步骤如下: ...

  3. Haskell 参考资料

    1.Haskell 中文社区:www.haskellcn.org 2.Haskell   官网:     www.haskell.org 3.Haskell   函数查询:www.haskell.or ...

  4. Eclipse - 修改默认user和类的创建日期

    1.找到eclipse.ini文件 2.在文件中找到 -vmargs -Duser.name=xxxxxxxx 3.修改xxxxxxxx为你的名字 4.eclipse中:Window -> Pr ...

  5. 2、Runtime Area Data

    这个也分为两大部分 1.是线程共享区域 ·线程共享区域又包括两部分Heap(堆)和方法区(Perm) 2.是线程独享区域 这个也包括两大部分程序计数器和栈 栈(又包括两部分:VM 栈和本地方法栈)

  6. 简单尝试利用vultr vps自架PPTP上网用于工作学习需要

    因为学习和工作的需要用到登陆海外网站查阅相关的资料和文档,之前有需要使用的时候是问网友索要的账户登录本地电脑拨号的,但是老是跟别人要还是不好,决定自己尝试搭建一个长期使用.看到有不少的介绍提到VULT ...

  7. VisualSVN 4.0.11补丁原创发布

    VisualSVN 4.0.11补丁原创发布 目前是官方最新版本.

  8. 【转】Linux查看机器负载

    转自 http://blog.csdn.net/szchtx/article/details/38455385 感谢 负载(load)是Linux机器的一个重要指标,直观了反应了机器当前的状态.如果机 ...

  9. DataList无数据如何显示

    <FooterTemplate> <asp:Label runat="server" ID="emptyLb" Text="No D ...

  10. 《java小应用程序(Applet)和java应用程序(Application)分别编写的简单计算器》

    Application和Java Applet的区别.Java语言是一种半编译半解释的语言.Java的用户程序分为两类:Java Application和Java Applet.这两类程序在组成结构和 ...