(课堂笔记)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有)
相关推荐
ClouGence6 天前
Oracle 数据同步为什么会出现数据不一致?长事务是常被忽略的原因
数据库·后端·oracle
ClouGence12 天前
Oracle CDC 架构优化:从主库直连到 DataGuard 备库同步
数据库·后端·oracle
曹牧13 天前
Oracle EXPLAIN PLAN
数据库·oracle
贤时间13 天前
codex 助力oracle ebs 开发
数据库·oracle
秉承初心13 天前
PostgreSQL 数据性能瓶颈突破实战
数据库·postgresql·oracle
Curvatureflight13 天前
MySQL 深分页越来越慢?从 LIMIT OFFSET 改成游标分页
数据库·oracle
XZ-07000113 天前
MySQL事务
数据库·mysql·oracle
tiancaijiben13 天前
阿里云函数计算FC如何实现网站的定时任务与自动化
数据库·oracle·dba
xfhuangfu13 天前
Oracle 19c 多租户体系架构介绍
数据库·oracle·架构
杨云龙UP13 天前
Spotlight 接入 Oracle 数据库监控操作指南 2026-06-16
数据库·oracle·性能监控·预警·阈值·spotlight·瓶颈分析