(课堂笔记)Oracle 表关联:连接类型、数据发散、自关联、同环比计算

本文系统梳理了Oracle表关联的核心知识,包括:

  1. 连接类型:详细解析INNER JOIN(只返回匹配记录)、LEFT JOIN(保留左表全部)、RIGHT JOIN(保留右表全部)和FULL JOIN(保留两表全部)四种连接方式的特点和使用场景。

  2. 数据发散问题:说明一对多或多对多关系时可能产生的笛卡尔积现象,以及如何通过正确设置连接条件避免数据膨胀。

  3. 自关联技术:演示如何使用表别名实现同一张表的自我连接,典型应用于查询层级关系(如员工-领导关系)。

  4. 实用计算:提供同环比增长率的SQL实现方法,展示如何通过表连接计算业务指标。

  5. 优化建议:给出连接查询的性能优化技巧和常见陷阱的规避方法,包括NULL值处理、连接顺序选择等最佳实践。


课堂笔记


根据你提供的课堂笔记,以下是对 Oracle 表关联 的详细总结与梳理,涵盖连接类型、数据发散、自关联、同环比计算等核心内容。


一、连接类型详解

1. INNER JOIN(内连接)

  • 返回:两表匹配的记录

  • 特点:不匹配的数据不显示

sql

复制代码
SELECT * 
FROM 中国移动 M
INNER JOIN 中国联通 N ON M.姓名 = N.姓名;
-- 结果:只显示张三、李四(两表都有的)

2. LEFT JOIN(左连接)

  • 返回:左表全部 + 右表匹配部分

  • 特点:左表数据不丢失,右表无匹配则为 NULL

sql

复制代码
SELECT * 
FROM 中国移动 M
LEFT JOIN 中国联通 N ON M.姓名 = N.姓名;
-- 结果:张三、李四、王五(王五在联通表无对应)

3. RIGHT JOIN(右连接)

  • 返回:右表全部 + 左表匹配部分

  • 特点:右表数据不丢失,左表无匹配则为 NULL

sql

复制代码
SELECT * 
FROM 中国移动 M
RIGHT JOIN 中国联通 N ON M.姓名 = N.姓名;
-- 结果:张三、李四、熊大(熊大在移动表无对应)

4. FULL JOIN(全外连接)

  • 返回:两表全部数据

  • 特点:双方数据都不丢失

sql

复制代码
SELECT * 
FROM 中国移动 M
FULL JOIN 中国联通 N ON M.姓名 = N.姓名;
-- 结果:张三、李四、王五、熊大(全部保留)

✅ 全连接注意事项:

sql

复制代码
-- 正确写法:使用 NVL 处理可能为 NULL 的字段
SELECT 
    NVL(M.姓名, N.姓名) AS 姓名,  -- 关键:连接字段要用 NVL
    NVL(M.话费, 0) + NVL(N.话费, 0) AS 总话费
FROM 中国移动 M
FULL JOIN 中国联通 N ON M.姓名 = N.姓名;

二、数据发散(笛卡尔积)

产生原因

当连接条件满足 一对多多对多 关系时,会产生数据发散。

典型示例

sql

复制代码
-- 1. 无条件连接 = 笛卡尔积
SELECT * 
FROM EMP E
CROSS JOIN DEPT D;  -- 14行 × 4行 = 56行

-- 2. 等价写法
SELECT * 
FROM EMP E, DEPT D;  -- 老式写法
SELECT * 
FROM EMP E
LEFT JOIN DEPT D ON 1=1;  -- 恒真条件

📊 行数推算规则

场景1:基于ID范围

  • A表:ID 1~100(100行)

  • B表:ID 61~120(60行)

  • 交集:61~100(40行)

连接类型 返回行数
INNER JOIN 40 行(交集)
LEFT JOIN 100 行(左表全部)
RIGHT JOIN 60 行(右表全部)
FULL JOIN 120 行(并集)

场景2:基于表记录数

  • A表:10行

  • B表:5行

连接类型 最多行数 最少行数
INNER JOIN 50(笛卡尔积) 0(无匹配)
LEFT JOIN 50(笛卡尔积) 10(无匹配)
RIGHT JOIN 50(笛卡尔积) 5(无匹配)
FULL JOIN 50(笛卡尔积) 10(无匹配)

💡 口诀

  • 最少行数:INNER可为0,LEFT不少于左表,RIGHT不少于右表,FULL不少于大表

  • 最多行数:都是笛卡尔积(M × N)


三、自关联(Self Join)

定义

同一张表自己与自己连接,需要使用不同的别名区分不同角色。

典型场景:上下级关系

sql

复制代码
-- 示例:员工及其领导信息
SELECT 
    E.ENAME AS 员工姓名,
    E.SAL AS 员工薪资,
    F.ENAME AS 领导姓名,
    F.SAL AS 领导薪资
FROM EMP E           -- 员工表(角色:员工)
LEFT JOIN EMP F      -- 领导表(角色:领导)
ON E.MGR = F.EMPNO;  -- 员工的领导编号 = 领导的员工编号

复杂示例:带部门信息

sql

复制代码
SELECT 
    E.ENAME AS 员工姓名,
    E.SAL AS 员工薪资,
    D.DNAME AS 员工部门,
    F.ENAME AS 领导姓名,
    F.SAL AS 领导薪资,
    K.DNAME AS 领导部门
FROM EMP E
INNER JOIN DEPT D ON E.DEPTNO = D.DEPTNO
LEFT JOIN EMP F ON E.MGR = F.EMPNO
LEFT JOIN DEPT K ON F.DEPTNO = K.DEPTNO;

四、实际应用:同环比计算

场景:计算每月环比增长率

公式:(本期 - 上期) / 上期 = 本期/上期 - 1

sql

复制代码
-- 创建销售表
CREATE TABLE T_SALES(
    MONTH NUMBER,
    AMOUNT NUMBER
);

INSERT INTO T_SALES VALUES (4,4432);
INSERT INTO T_SALES VALUES (5,434);
INSERT INTO T_SALES VALUES (6,232);
INSERT INTO T_SALES VALUES (7,46554);
INSERT INTO T_SALES VALUES (8,76);
INSERT INTO T_SALES VALUES (9,454);
COMMIT;

-- 计算环比增长率
SELECT 
    M.MONTH AS 月份,
    M.AMOUNT AS 本月销售额,
    N.AMOUNT AS 上月销售额,
    ROUND((M.AMOUNT / N.AMOUNT - 1) * 100, 2) || '%' AS 环比增长率
FROM T_SALES M                    -- 本月数据
LEFT JOIN T_SALES N ON M.MONTH - 1 = N.MONTH;  -- 上月数据

扩展:同比计算(去年同期)

sql

复制代码
-- 假设有年份字段
LEFT JOIN T_SALES N ON M.YEAR - 1 = N.YEAR AND M.MONTH = N.MONTH

五、重点总结

✅ 连接类型选择指南

需求 推荐连接
只要匹配的数据 INNER JOIN
左表数据全要 LEFT JOIN
右表数据全要 RIGHT JOIN
两表数据全要 FULL JOIN
避免数据发散 确保连接条件能唯一匹配

✅ 常见陷阱

  1. 忘记处理 NULL :全连接中使用 NVL 处理可能为 NULL 的字段

  2. 数据发散:连接前确认关联字段是否唯一

  3. 自关联忘记别名:必须用不同别名区分同一张表

  4. 连接顺序影响性能:小表驱动大表会更高效

✅ 调试技巧

sql

复制代码
-- 1. 先查两表的唯一性
SELECT 关联字段, COUNT(*) 
FROM 表名 
GROUP BY 关联字段 
HAVING COUNT(*) > 1;

-- 2. 用小数据集验证连接结果
SELECT * FROM 表名 WHERE ROWNUM <= 10;

-- 3. 逐步添加连接条件
-- 先做单表查询,确认数据正确,再加 JOIN

六、练习答案参考

验证行数极值

sql

复制代码
-- 1. INNER JOIN 无匹配(最少0行)
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON 1=2;  -- 0行

-- 2. LEFT JOIN 无匹配(最少10行)
SELECT * FROM TABLEA A
LEFT JOIN TABLEB B ON 1=2;  -- 10行(A表全保留)

-- 3. RIGHT JOIN 全匹配(最多5×10=50行)
SELECT * FROM TABLEA A
RIGHT JOIN TABLEB B ON 1=1;  -- 50行

-- 4. FULL JOIN 基于ID(返回并集)
SELECT * FROM TABLEA A
FULL JOIN TABLEB B ON A.ID = B.ID;  -- 10行(1-5匹配,6-10仅A有)
相关推荐
Irene19917 小时前
(课堂笔记)Oracle 常用函数:数值、字符串、日期处理
oracle·函数
cyber_两只龙宝8 小时前
【Oracle】Oracle数据库的登录验证
linux·运维·数据库·sql·云原生·oracle
杨云龙UP19 小时前
ODA登录ODA Web管理界面时提示Password Expired的处理方法_20260423
linux·运维·服务器·数据库·oracle
尚雷55801 天前
从电商订单支付更新,吃透 Oracle 数据修改的底层设计哲学与全组件协同原理
数据库·oracle
李兆龙的博客1 天前
从一到无穷大 #70 从 LR 图 PEC 到InfluxQL兼容性差分测试方法论与工程实践
数据库·功能测试·oracle
张子行的博客1 天前
SQL 调优实战:跨表排序性能提升之路
数据库·sql·oracle
FinTech老王1 天前
逻辑删除不等于物理销毁:KingbaseES敏感数据标记与销毁实操指南
数据库·安全·oracle
池佳齐1 天前
软考高级系统架构设计师备考(十八):数据库系统—事务管理与并发控制
数据库·oracle·系统架构
Irene19911 天前
数据库“水位线”概念详解:Oracle数据库的数据文件空间管理 和 Flink/流处理中的事件时间处理
数据库·oracle