1.按照salary排序 显示s_emp 表中的 id first_name salary 如果工资相同
则使用 first_name 降序排列
2.写出处理字符串的 函数有哪些 写 5 个
3.分别写出 round(12.88) trunc(12.88) round(12.88,1) trunc(12.88,1)
round(3.33) trunc(3.33) 的值
4.显示 s_emp 表中first_name 的前三个字符 和 后三个字符 并把这些数据 变大写
5.显示s_emp 表中第三个字符是a的 first_name
6.显示 s_emp 表中 manager_id 是NULL的员工 显示 id first_name salary
7.显示 s_emp 表中 first_name 叫 Carmen 并且 salary 等于 2500 的员工
显示 id first_name salary
select id,first_name,salary from s_emp
where first_name='Carmen' and salary=2500;
--------------------------------------------------------------------
1.多表查询 10*10*10
1.1 为什么要有多表查询
需要的数据 已经被分散多张表中了。
1.2 如何实现?
查询 每个员工的 first_name 和 对应的部门编号
select first_name,dept_id from s_emp;
在上面查询的基础上 显示部门名
select first_name,dept_id,name
from s_emp,s_dept;
上面的查询 产生了一个超大集合 叫 笛卡尔积
select first_name,dept_id,name
from s_emp,s_dept where dept_id=id;
上面的语句出错 需要使用规则:多张表中有同名的字段 使用 表名 点 区分
select first_name,dept_id,name
from s_emp,s_dept
where dept_id=s_dept.id;
1.3 语法
select 需要的字段
from 表1,表2 where 表的连接条件;
1.4 练习
s_dept 部门表 s_region 地区表
id number 部门编号 id number 地区编号
name varchar2(25) 部门名 name varchar2(25) 地区名
region_id number 地区编号
显示 每个部门的名字 和 对应的地区的名字
select s_dept.name,s_region.name
from s_dept,s_region
where region_id=s_region.id;
1.5 使用表的别名 简化查询
select d.name,r.name
from s_dept d,s_region r
where region_id=r.id;
1.6 等值连接 和 非等值连接
员工 和 部门 dept_id = s_dept.id
部门 和 地区 region_id = s_region.id
表达两张表的关系 使用等号 则称之为 等值连接。
如果连接两张表的关系 不使用等号 则称之为非等值连接
salgrade 工资级别表
SQL> desc salgrade;
Name
---------------------
GRADE 级别
LOSAL 级别对应的低工资
HISAL 级别对应的高工资
显示 s_emp 表中 每个人的id , salary 和 salary 对应的工资级别
select id,salary,grade
from s_emp,salgrade
where salary between losal and hisal;
1.7 自连接
一张物理表中 存储了两层业务含义的数据 要把其中的一层业务含义的数据查询出来 就需要
使用到自连接的语法。
s_emp
领导
普通员工
把所有的领导查询出来?
id manager_id
80 60
100 100
101 100
102 100
110 100
select id,first_name from s_emp where id=manager_id;
当有人的manager_id 是你的id 时 则 你就是领导
select distinct m.id,m.first_name
from s_emp e,s_emp m where e.manager_id = m.id;
8 个领导
25-8=17个普通员工 下面的写法错误
select distinct m.id,m.first_name
from s_emp e,s_emp m where e.manager_id != m.id;
2.内连接
内连接的特点就是 符合连接条件的数据 被选中 不符合连接条件的数据被过滤掉。
上面的 等值连接 非等值连接 自连接 都是内连接。
3.外连接
3.1 概念和实现
外连接的结果集 等于 内连接的结果集 加上 匹配不上的记录
(一个也不能少)
如何实现?
(+) (+) 所在的表的字段 对面的表的数据全部被匹配出来
底层通过 NULL 记录匹配出来的
select distinct m.id,m.first_name
from s_emp e,s_emp m where e.manager_id(+) = m.id
and e.manager_id is null;
3.2 练习 s_emp s_dept
显示每个员工的id, first_name 和 对应的 部门名(name)
select e.id,first_name,name
from s_emp e,s_dept d
where e.dept_id=d.id;
公司为了业务发展 需要抽调一部分人出来 这些人将离开原来的部门
update s_emp set dept_id = null where id < 3;
commit;
显示每个员工的id, first_name 和 对应的 部门名(name) 没有部门编号的员工也要显示
select e.id,first_name,name
from s_emp e,s_dept d
where e.dept_id=d.id(+);
3.3 练习 s_dept s_region
显示每个部门的名字 和 对应的地区的名字
select d.id, d.name,r.name
from s_dept d,s_region r
where d.region_id = r.id;
公司业务扩大了 增加了一些新的部门
insert into s_dept values(100,'test100',NULL);
insert into s_dept values(101,'test101',NULL);
commit;
显示每个部门的名字 和 对应的地区的名字 没有地区编号的部门也要显示
select d.id, d.name,r.name
from s_dept d,s_region r
where d.region_id = r.id(+);
3.4 非等值连接的外连接 salgrade s_emp
列出每个员工的 id salary 和 salary 对应的工资级别
select id,salary,grade
from s_emp,salgrade
where salary between losal and hisal;
把 id = 25 和 id=24 的这两个人的工资 改成 12345
update s_emp set salary=12345 where id >= 24;
commit;
列出每个员工的 id salary 和 salary 对应的工资级别 超出统计范围的员工也要显示
select id,salary,grade
from s_emp,salgrade
where salary between losal(+) and hisal(+);
4.表连接
内连接
等值连接 员工和部门 部门和地区
非等值连接 员工的工资 和 对应的工资级别
自连接 谁是领导?
外连接
等值连接 员工和部门 (找出没有部门的员工) 部门和地区 (没有地区编号的部门)
非等值连接 员工的工资 和 对应的工资级别 (超出统计范围的工资)
自连接 谁是普通员工?
外连接的结果集 等于 内连接的结果集 加上匹配不上的记录
如何实现的?
(+) (+)的意思所在字段的对面的表的数据全部被匹配出来
本质上 底层是通过 NULL 记录进行的匹配
5.SQL99 内外连接
5.1 内连接标准
from a表 join b表 on 连接条件 where 过滤条件;
from a表 inner join b表 on 连接条件 where 过滤条件;
显示 每个部门的名字 和 对应的地区的名字
select d.name,r.name
from s_dept d,s_region r
where d.region_id = r.id;
select d.name,r.name
from s_dept d join s_region r
on d.region_id = r.id;
select d.name,r.name
from s_dept d inner join s_region r
on d.region_id = r.id;
5.2 外连接的标准
a表 left outer join b 表 on 表的连接条件 where 过滤条件;
a表 right outer join b 表 on 表的连接条件 where 过滤条件;
a表 full outer join b 表 on 表的连接条件 where 过滤条件;
a表 left outer join b 表 就是a表发起连接 意思就是a表的数据全部被匹配出来。
a表 right outer join b 表 就是b表发起连接 意思就是 b表的数据全部被匹配出来。
本质上也通过 NULL 记录进行的匹配
显示每个部门的名字 和 对应的地区的名字 没有地区编号的部门也要显示
select d.id, d.name,r.name
from s_dept d,s_region r
where d.region_id = r.id(+);
select d.id, d.name,r.name
from s_dept d left outer join s_region r
on d.region_id = r.id;
select d.id, d.name,r.name
from s_region r right outer join s_dept d
on d.region_id = r.id;
使用左外连接 实现 s_emp 谁是普通员工的问题 显示 id first_name
谁是领导?40 谁是普通员工 40 改成 left outer join 20
select distinct m.id,m.first_name
from s_emp e,s_emp m
where e.manager_id(+) = m.id and e.manager_id is null;
select distinct m.id,m.first_name
from s_emp m left outer join s_emp e
on e.manager_id = m.id where e.manager_id is null;
select distinct m.id,m.first_name
from s_emp m left join s_emp e
on e.manager_id = m.id where e.manager_id is null;
5.3 full outer join
全外连接 只是一个逻辑概念,代表左外连接的结果集 加上 右外连接的结果集 然后
排除重复的记录。
Oracle 中如何实现全外连接呢? 不是通过两端都加(+) 实现的。
而是通过 union 来实现的 , union 的意思是 合并两个结果集 然后排重。
union all 合并两个结果集 不排重。
select id from s_emp union select id from s_emp;
select id from s_emp union all select id from s_emp;
6.组函数
6.1 特点
对一组数据处理 最终返回一个结果 无论sql语句影响多少行 最终只有一个结果。
6.2 常见的组函数
max(par1) 统计最大值
min(par1) 统计最小值
avg(par1) 统计平均值
sum(par1) 统计和
count(par1) 统计个数
6.3 练习
统计s_emp 表中的最高工资 最低工资 员工的个数
select max(salary),min(salary),count(id) from s_emp;
统计s_emp 表中的工资的和 以及 工资的平均值
select sum(salary),avg(salary) from s_emp;
6.4 特殊用法
在count 中可以使用 *
select count(*) from s_emp;
组函数中可以使用 distinct
select sum(distinct salary),avg(salary) from s_emp;
6.5 组函数 对NULL 值如何处理? 忽略
select max(manager_id) from s_emp;
select avg(manager_id) from s_emp;
7.分组
7.1 概念
按照一定的标准 把数据分割成若干部分
7.2 提出问题
按照部门编号分组 统计每个部门的人数
dept_id count
41 3
42 4
50 2
7.3 sql 中如何完成
select 字段名,统计的数据 from 表名 where 条件
group by 分组标准 having 组数据过滤条件
order by 排序标准;
按照部门编号分组 统计 每个部门的人数 显示 部门编号 和 平均工资
select dept_id,count(id)
from s_emp
group by dept_id;
按照部门编号 分组 统计 每个部门的平均工资 显示 部门编号 和 平均工资
select dept_id,avg(salary)
from s_emp
group by dept_id;
7.4 练习 s_dept
按照地区编号 分组 统计每个地区中的部门个数 显示地区编号 和 部门个数
select region_id,count(id)
from s_dept
group by region_id;
要求地区中部门个数大于2 的显示
select region_id,count(id)
from s_dept
group by region_id having count(id) > 2;
7.5 按照部门编号分组 统计每个部门的平均工资 要求平均工资大于1400 的 显示
select dept_id,avg(salary)
from s_emp
group by dept_id having avg(salary) > 1400;
having 执行早 还是 select 执行早?