当前位置: 首页 > news >正文

[Oracle数据库] Oracle 复杂查询

对于刚接触 Oracle 数据库的初学者来说,简单查询(如SELECT * FROM 表名)可能不难掌握,但面对复杂业务场景时,就需要更强大的查询能力。本文将围绕 Oracle 复杂查询的核心知识点展开,包括条件逻辑、分组函数、分组查询、子查询、分页及合并查询,用通俗的语言和实例帮你快速入门。

一、条件逻辑:让查询学会 “判断”

在 SQL 中,我们经常需要根据不同条件返回不同结果,这就需要用到条件逻辑。Oracle 中最常用的条件逻辑工具是CASE...WHEN语句,它类似其他编程语言中的if-else结构。

1️⃣逻辑判断 vs 条件判断

  • 逻辑判断:用ANDORNOT等逻辑运算符对条件表达式进行计算,最终返回truefalse(例如:sal > 1000 AND deptno = 20)。
  • 条件判断:根据条件决定执行哪个分支的操作(例如:“如果工资低于 1500,返回‘低’;否则返回‘高’”)。

2️⃣CASE...WHEN:两种实用形式

CASE...WHEN有两种形式,分别适用于不同场景:

(1)简单 CASE 表达式:匹配固定值

当需要将一个表达式的值与多个固定值对比时,用简单 CASE。

语法:

sql

CASE 表达式WHEN 值1 THEN 结果1WHEN 值2 THEN 结果2...ELSE 默认结果
END

实例:根据员工职位返回不同问候语

sql

SELECT EMPNO, ENAME, CASE job WHEN 'PRESIDENT' THEN '总裁辛苦了' WHEN 'MANAGER' THEN '经理好' WHEN 'ANALYST' THEN '组长干的不错' WHEN 'SALESMAN' THEN '跑业务去' WHEN 'CLERK' THEN '嗯' END 问候语 
FROM emp;
(2)搜索 CASE 表达式:处理复杂条件

当条件是范围、多字段组合等复杂逻辑时,用搜索 CASE。

语法:

sql

CASEWHEN 条件1 THEN 结果1WHEN 条件2 THEN 结果2...ELSE 默认结果
END

实例:根据工资范围划分等级

sql

SELECT EMPNO, ENAME, CASE WHEN sal < 1500 THEN 'Low' WHEN sal BETWEEN 1500 AND 2000 THEN 'Medium' WHEN sal > 2000 THEN 'High' ELSE 'Unknown' END AS salary_grade 
FROM emp;

二、分组函数:对数据 “汇总计算”

分组函数(又称聚合函数)用于对一组数据进行计算并返回单个结果,常与分组查询配合使用。核心注意点:分组函数不能直接与非分组字段同时出现在SELECT中(除非非分组字段在GROUP BY中)。

常用分组函数及实例

函数作用实例(基于 emp 表)
COUNT统计非空值的数量SELECT COUNT(sal) FROM emp;(统计有工资的员工数)
MIN求列的最小值SELECT MIN(sal) FROM emp;(查询最低工资)
MAX求列的最大值SELECT MAX(sal) FROM emp;(查询最高工资)
AVG求列的平均值(忽略 NULL)SELECT AVG(sal) FROM emp;(查询平均工资)

小提示:如果要包含 NULL 值计算(例如工资为 NULL 时按 0 处理),可结合NVL函数:AVG(NVL(sal, 0))

三、分组查询:按规则 “拆分数据”

当需要按某一列(如部门、职位)拆分数据并分别计算时,需用GROUP BY子句。

1️⃣GROUP BY 基础用法

语法:

sql

SELECT 分组字段, 分组函数
FROM 表名
GROUP BY 分组字段;

实例:

  • 按部门编号统计员工人数:

    sql

    SELECT deptno, COUNT(*) AS "人数" FROM emp GROUP BY deptno;
    
  • 按部门和职位统计人数(多字段分组):

    sql

    SELECT deptno, job, COUNT(*) FROM emp GROUP BY deptno, job ORDER BY deptno;
    

注意:GROUP BY后的字段可不包含在SELECT中(但通常会包含以便区分分组)。

2️⃣HAVING:对分组结果 “二次过滤”

HAVING子句用于过滤分组后的结果,与WHERE的区别如下:

特性WHEREHAVING
执行时机分组前过滤数据分组后过滤分组结果
能否用聚合函数不能

实例:

  • 查询员工人数大于 5 的部门:

    sql

    SELECT deptno, COUNT(*) FROM emp GROUP BY deptno HAVING COUNT(*) > 5;
    
  • 查询 20 号部门的最低工资(分组后过滤):

    sql

    SELECT MIN(sal) FROM emp GROUP BY deptno HAVING deptno = 20;
    

四、子查询:让查询 “嵌套起来”

当一次查询无法完成需求时(例如 “先查 A 的部门,再查该部门所有员工”),可以用子查询(嵌套在其他 SQL 中的SELECT语句)。

子查询的基本规则

  • 必须用括号()包裹;
  • 可嵌套多层;
  • 根据返回结果行数,分为单行、多行、多列子查询。

1️⃣单行子查询:返回 1 行结果

=><等运算符连接,适用于子查询结果唯一的场景。

实例:查询 SMITH 所在部门的所有员工

sql

SELECT ename, sal, deptno 
FROM emp 
WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SMITH');

2️⃣多行子查询:返回多行结果

需用INALLANY等运算符:

  • IN:匹配子查询结果中的任意一个值;
  • ALL:匹配子查询结果中的所有值;
  • ANY:匹配子查询结果中的任意一个值(与IN类似,但ANY可结合比较运算符)。

实例:

  • IN查询与 10 号部门工种相同的员工:

    sql

    SELECT ename, job, sal, deptno 
    FROM emp 
    WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10);
    
  • ALL查询工资高于 30 号部门所有人的员工:

    sql

    SELECT ename, sal, deptno 
    FROM emp 
    WHERE sal > ALL (SELECT sal FROM emp WHERE deptno = 30);
    

    (等价于sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30),效率更高)

3️⃣多列子查询:返回多列结果

当条件涉及多个字段时,用多列子查询。

实例:查询与 SMITH 同部门且同工种的员工

sql

SELECT ename, job, sal, deptno 
FROM emp 
WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH');

4️⃣子查询的常见应用场景

  • 在 FROM 中使用:作为虚拟表(需指定别名),例如查询各部门中工资高于部门平均的员工:

    sql

    SELECT emp.deptno, ename, sal, dept.avgsal 
    FROM emp, (SELECT deptno, AVG(sal) AS avgsal FROM emp GROUP BY deptno) dept 
    WHERE emp.deptno = dept.deptno AND sal > dept.avgsal;
    
  • 在 DML 中使用:

    • 插入数据:INSERT INTO 表名 SELECT ...
    • 更新数据:UPDATE 表名 SET ... = (子查询)
    • 删除数据:DELETE FROM 表名 WHERE ... = (子查询)
  • 在 DDL 中使用:复制表结构和数据(加WHERE 1=2只复制结构):

    sql

    CREATE TABLE new_emp(id, name, sal, job, deptno) 
    AS SELECT empno, ename, sal, job, deptno FROM emp;
    

五、分页查询:批量数据 “分段显示”

Oracle 中通过伪列实现分页,常用的伪列有rownum(逻辑编号,从 1 开始)和rowid(物理编号)。其中rownum最常用。

rownum 分页的关键步骤

rownum的特性:总是从 1 开始编号,若结果集中没有rownum=1,则后续编号也不存在(因此不能直接用rownum >=6 AND rownum <=9)。

查询第 6-9 条记录的步骤:

  • 先获取前 10 条记录并编号:

    sql

    SELECT e.*, rownum rn FROM (SELECT * FROM emp) e WHERE rownum <= 10;
    
  • 嵌套查询,筛选编号大于 6 的记录:

    sql

    SELECT * FROM (SELECT e.*, rownum rn FROM (SELECT * FROM emp) e WHERE rownum <= 10
    ) WHERE rn > 6;
    

六、合并查询:多结果集 “组合运算”

UNIONUNION ALLINTERSECTMINUS组合多个查询结果,适用于大数据量场景。

操作符作用示例(查询工资 > 2500 或职位为 MANAGER 的员工)
UNION并集(去重)SELECT ... WHERE sal>2500 UNION SELECT ... WHERE job='MANAGER'
UNION ALL并集(不去重,效率更高)SELECT ... UNION ALL SELECT ...
INTERSECT交集(同时存在于两个结果集)SELECT ... INTERSECT SELECT ...
MINUS差集(存在于第一个集但不在第二个)SELECT ... MINUS SELECT ...

注意:组合的查询结果需列数相同、类型兼容;LOB、LONG 等特殊类型不支持部分操作符。

总结

Oracle 复杂查询是数据库操作的核心技能,本文涵盖了条件逻辑(CASE...WHEN)、分组函数、分组查询(GROUP BY+HAVING)、子查询、分页及合并查询等重点。初学者需注意:

  • 分组函数与GROUP BY的配合使用;
  • WHEREHAVING的区别;
  • 子查询的嵌套逻辑和rownum分页的特性。
http://www.dtcms.com/a/334678.html

相关文章:

  • 8.15 JS流程控制案例+解答
  • java 面试八股集锦
  • K8S HPA 弹性水平扩缩容 Pod 详解
  • 西门子SMART PLC监控时间戳问题BUG修复
  • Cursor执行命令卡顿解决办法(Cursor卡住、Cursor命令卡住、Cursor执行慢、Cursor执行命令慢)改成以管理员身份运行就好!!!
  • 《探索IndexedDB实现浏览器端UTXO模型的前沿技术》
  • 【CPP】自己实现一个CPP小工具demo,可以扩展其他选项
  • homebrew 2
  • pytorch例子计算两张图相似度
  • 创建maven module中的override
  • Maven下载和配置-IDEA使用
  • 自动化测试的下一站:AI缺陷检测工具如何实现“bug提前预警”?
  • uniapp跨端适配方案
  • Qt 动态属性(Dynamic Property)详解
  • SDN安全开发环境中常见的框架,工具,第三方库,mininet常见指令介绍
  • 【基础-判断】HarmonyOS提供了基础的应用加固安全能力,包括混淆、加密和代码签名能力
  • 守护品质安全,防伪溯源系统打造全链路信任体系
  • 物联网 (IoT) 的顶级硬件平台
  • IEEEtaes.cls解析
  • python---模块
  • 防御保护15
  • YOLOv8环境配置命令
  • GCN图卷积神经网络的Pytorch实现
  • Azure AI Search 探索总结
  • 数据库索引视角:对比二叉树到红黑树再到B树
  • 【计算机视觉与深度学习实战】03基于Canny、Sobel和Laplacian算子的边缘检测系统设计与实现
  • DeepSeek-R1-深度解析-通过强化学习激励大语言模型的推理能力
  • Spring AI 玩转工具调用:模型帮你精确设闹钟
  • 九尾狐未来机械锂晶核
  • 盲盒抽谷机小程序系统开发:从0到1的完整方法论