(课堂笔记)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有)
相关推荐
数据最前线1 小时前
雪上加霜,Oracle向蓝色巨人最后的阵地发起挑战
数据库·oracle
正在走向自律3 小时前
数据集成软件怎么选、怎么用:从 KFS 的建表、增删改查到一致性校验全流程
oracle·kingbasees·断点续传·全量+增量同步·多通道并行·事务一致性
云贝贝贝4 小时前
Oracle 认证实战指南
数据库·oracle
达梦数据4 小时前
达梦数据复制软件DMDRS搭建部署示例:源数据库DMDPC到目标数据库DM8一对一数据同步
数据库·oracle
AlfredZhao4 小时前
SQLcl 用文件夹直观管理数据库连接
oracle
江湖有缘17 小时前
Docker实战 | 使用Docker部署rmoments社交平台
jvm·docker·oracle
for_ever_love__17 小时前
MySQL SELECT 与 WHERE 优化实战:可搜索条件、联合索引与执行计划
数据库·mysql·oracle·select·where·条件优化·查询优化技巧
路远的数据库笔记19 小时前
Oracle报ORA-00020连接打满?从专用进程模型到静态参数,一次生产排查全记录
数据库·oracle·国产数据库·ora-00020·dba实战·sharedserver
dishugj1 天前
HANA监控、巡检与切换演练
数据库·oracle
oradh1 天前
Oracle 索引维护操作总结
数据库·oracle