Oracle_day2 单行函数|组函数|分组|伪列|子查询|分页|多表连接

一、案例:检查 1997 年入职的员工

复制代码
Select * from employees where to_char(hire_date,'yyyy') like '1997';

二、单行函数补充

单行函数特点

单行函数会作用于每一行指定的数据,每一行产生一个结果

三、组函数(聚合函数)

组函数特点

组函数作用于一组数据,一组只产生一个结果

常用组函数

表格

函数 说明
avg(字段) 求平均值
sum(字段) 求和
max(字段) 求最大值
min(字段) 求最小值
count(字段) 统计行数

案例

1. 查询所有员工平均工资
复制代码
Select avg(salary) from employees;
2. 查询平均工资、工资总和、最高工资、最低工资
复制代码
Select avg(salary),sum(salary),max(salary),min(salary) from employees;
3. 统计公司员工数量
复制代码
--方式1:统计表全部非空行
select count(*) from employees;

--方式2:统计主键,主键非空,推荐
select count(employee_id) from employees;

--方式3:统计该字段非空的行数,null会被自动忽略
select count(commission_pct) from employees;

💡注意:count(字段)自动忽略字段为 null 的行 ;统计全表记录优先使用count(*)count(主键)

四、分组查询 --- group by

语法

复制代码
select 字段 ... from 表名 where ... group by 字段 order by...;

group by 后面填写分组条件字段。

案例 1:查询各个部门的平均工资

分组条件:department_id 部门编号

复制代码
Select avg(salary) from employees group by department_id;

案例 2:查询各个部门、各个职位员工的平均工资

分组条件:department_id,job_id

复制代码
Select department_id,job_id,avg(salary) 
from employees 
group by department_id ,job_id;

⚠️ group by 使用三大原则

  1. 出现在 group by 子句中的字段,才可以直接写在 select 子句中
  2. 没有出现在 group by 的字段,必须配合组函数写在 select 中
  3. 如果 group by 中字段使用单行函数,select 对应字段也要使用相同单行函数。

案例:查询 1997 年各个月份入职员工总人数

  1. where 筛选 1997 年数据

  2. 按入职月份分组

  3. count 统计数量

    Select count(*)
    From employees
    Where to_char(hire_date,'yyyy')='1997'
    Group by to_char(hire_date,'mm');

五、Having 条件筛选子句

having对分组之后的结果做二次筛选。 where:分组之前对原始数据筛选。

完整语法

复制代码
select 字段 ...from 表名 where ... group by ... having...order by;

案例 1:查询 1997 各个月份入职人数,只展示人数大于 3 的月份

复制代码
Select count(*)
From employees
Where to_char(hire_date,'yyyy')='1997'
Group by to_char(hire_date,'mm')
Having count(*)>3;

案例 2:查询 50、60、90 号部门各自平均工资

方式① having 实现(不推荐)
复制代码
Select department_id,avg(salary)
From employees
Group by department_id
Having department_id in(50,60,90);
方式② where 实现(推荐)
复制代码
Select department_id,avg(salary)
From employees
Where department_id in(50,60,90)
Group by department_id;

💡注意:where 和 having 都能实现的需求,优先使用 where。where 在分组前过滤,减少参与分组的数据量,性能更好。

六、Select 完整语句 & 执行顺序

完整 SQL 模板

复制代码
Select ... from...where...group by...having...order by...;

执行顺序(非常重要)

  1. From:确定查询哪一张表
  2. Where:原始数据初次筛选
  3. Group by:对筛选后的数据进行分组
  4. Having:分组完成后,对分组结果再次筛选
  5. Select:生成目标结果集
  6. Order by:对最终结果集排序

记忆口诀:查表→筛原始→分组→筛分组结果→输出列→排序

七、Oracle 伪列

伪列:Oracle 系统维护的特殊列,物理表中并不真实存在select *无法查询,必须手动指定列名。

1. rowid

rowid 是根据数据物理存储地址生成的 18 位唯一字符串。 rowid 定位数据效率极高;一般开发不会手动写,数据库内部自动使用。

复制代码
select employee_id,first_name,salary,rowid from employees;

2. rownum

rownum:给查询结果集生成自增序列号,永远从 1 开始

复制代码
select employee_id,first_name,salary,rownum from employees;
案例:查询前 5 名员工信息
复制代码
Select employee_id,first_name,salary
From employees where rownum<=5;

⚠️重点限制: rownum 做 where 条件:支持 =1<<=>=1不能直接写 rownum>1、rownum>=2

rownum 和 order by 的坑

❌错误写法:先截取,后排序,拿不到工资最高前 5

复制代码
Select employee_id,first_name,salary 
from employees where rownum<=5 
order by salary desc;

✅正确写法:子查询先排序,外层再用 rownum 截取

复制代码
select * from (select * from employees order by salary desc)
where rownum<=5;

💡小知识点:同时查询*和 rownum,表必须起别名

复制代码
Select e.*,rownum
From employees e;

八、子查询(嵌套查询)

子查询:select 语句内部再嵌入 select 语句。

①子查询返回:一行一列

需求:查询工资高于平均工资的员工信息

复制代码
select * from employees where salary>(select avg(salary) from employees);

②子查询返回:多行一列(配合 in)

需求:查询和 Steven 同一个部门的员工信息

复制代码
select * from employees
where department_id in (select department_id from employees where first_name='Steven');

③子查询返回多行多列(常用于排序后分页、取 topN)

需求:查询工资最高前 5 个人信息

复制代码
select * from (select * from employees order by salary desc)
where rownum<=5;

九、Oracle 分页查询【重点】

分页:将大批量数据分段展示,依靠rownum + 子查询实现。

案例 1:查询第 6~10 条员工信息

复制代码
select * from (select e.*,rownum rn from employees e)
where rn>=6 and rn<=10;

案例 2:查询工资最高的第 6~10 名员工信息

内层先排序生成结果集,再生成 rn,外层做区间过滤

复制代码
select * from (
    select e.*,rownum rn from (select * from employees order by salary desc) e
)
where rn>=6 and rn<=10;

十、表连接查询

多张表联合查询;查询字段分布在多张表时使用表连接。

1. 内连接 inner join

inner join:只返回满足连接条件的数据;连接字段为 null 的行会被过滤。

语法:

复制代码
select ... from tab1 t1 inner join tab2 t2 on 连接条件;

案例:查询员工编号、姓名、工资、部门名称 表:employeesdepartments 连接条件:e.department_id = d.department_id

复制代码
select e.employee_id,e.first_name,e.salary,d.department_name
from employees e inner join departments d 
on e.department_id=d.department_id;

2. 外连接

①左外连接 left join【重点】

左表全部记录保留;右表匹配不到数据自动补 null;outer关键字可以省略。

复制代码
select e.employee_id,e.first_name,e.salary,d.department_name
from employees e left join departments d 
on e.department_id=d.department_id;
②右外连接 right join

右表全部记录保留;左表匹配不到自动补 null。

复制代码
select e.employee_id,e.first_name,e.salary,d.department_name
from employees e right join departments d 
on e.department_id=d.department_id;
③全外连接 full outer join【了解】

两张表所有记录全部保留,匹配不到补 null

复制代码
select e.*,d.*
from employees e full outer join departments d 
on e.department_id=d.department_id;
④笛卡尔连接【了解】

不写连接条件,表的每一行互相全部配对,业务尽量避免。

复制代码
select e.*,d.*
from employees e,departments d;

3. 多表连接查询【掌握】

需求:查询员工编号、姓名、工资、部门名称、部门所在城市 涉及表:employeesdepartmentslocations

复制代码
select e.employee_id,e.first_name,e.salary,d.department_name,l.city
from employees e 
left join departments d on e.department_id=d.department_id
left join locations l on d.location_id=l.location_id;

多表连接执行逻辑:从左往右,先两张表连接,结果再和下一张表继续连接。

相关推荐
Sam_Deep_Thinking1 小时前
关于java final关键字的可见性
java·后端·面试·程序员
AAA代码批发商2 小时前
Days 47 IMX6ULL 裸机开发:按键轮询实验 + 外部中断原理剖析(上)
笔记·学习·imx6ull·裸机开发·#arm中断
sunoo-2292 小时前
【ARM嵌入式学习笔记Day6】一文打通i.MX6ULL时钟体系:PLL/PFD/预分频+滞回比较器全解析
arm开发·笔记·vscode·单片机·imx6ull·汇编语言
景煜拾年3 小时前
RHCA-Docker知识点整理
运维·笔记
NineData4 小时前
NineData 与统信服务器操作系统完成兼容认证
数据库·oracle·操作系统·软件·数据库管理工具·ninedata·统信
M78佐菲11 小时前
ARM学习笔记(1)
linux·arm开发·笔记·嵌入式硬件·学习
益达丫12 小时前
Socket编程揭秘:端口、IP与进程通信的底层逻辑
linux·笔记
Rain的Java大神之路13 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
淡海水13 小时前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp