欢迎光临
我们一直在努力

重难点复盘|多表 + 子查询真题演练,吃透核心(附面试真题)

前言

到本篇为止,我们已经完整学完了企业 SQL 80% 核心重难点:INNER/LEFT/RIGHT/FULL JOIN 多表联查、标量 / 列 / 行子查询、EXISTS/IN/ANY/ALL、UNION/UNION ALL 联合查询。这些内容是面试必考、工作高频、拉开差距的关键。

这一篇不讲新知识点,专门做高强度复盘 + 真题集训,把前面所有重难点串成体系、用企业真实面试题带你彻底吃透,做到学完就会、会了能用、用了不踩坑。


一、本章知识点汇总

  • 四大连接类型核心原理一句话总结
  • 子查询三大类型 + 四大关键字速记清单
  • UNION 与 UNION ALL 必背区别
  • 笛卡尔积、NULL、关联顺序三大坑点复盘
  • 企业高频面试真题(10 道)+ 详细答案
  • 多表 + 子查询混合实战综合题
  • 职场书写规范与优化黄金原则
  • 重难点思维导图式总结
  • 下一步学习路线指引

  • 二、重难点速记复盘(背会直接面试)

    1. 四大连接速记

    • INNER JOIN:取交集,只保留两边匹配数据
    • LEFT JOIN:左表全保留,右表不匹配补 NULL(工作最常用)
    • RIGHT JOIN:右表全保留,可转为 LEFT JOIN 写
    • FULL JOIN:两边全保留,MySQL 用 UNION 实现

    黄金原则:90% 场景用 LEFT JOIN,主表永远放左边。


    2. 子查询速记

    • 标量子查询:返回 1 个值,用 = > <
    • 列子查询:返回一列,用 IN/ANY/ALL
    • 行子查询:返回一行多列,(a,b)=(子查询)
    • EXISTS:只判断存在,大表性能最强
    • IN:小表好用,大表慎用
    • NOT IN:有 NULL 陷阱,生产禁用
    • NOT EXISTS:查询不存在数据的唯一安全写法

    黄金原则:大表关联用 EXISTS,非存在用 NOT EXISTS。


    3. 联合查询速记

    • UNION:合并 + 去重 + 排序,慢
    • UNION ALL:直接合并,极快
    • 语法铁律:列数相同、类型兼容、顺序一致
    • 排序:只在最后写一次 ORDER BY

    黄金原则:生产默认 UNION ALL。


    4. 三大致命坑复盘

  • 笛卡尔积:漏写 ON、一对多无分组 → 数据爆炸
  • NULL 陷阱:NOT IN、判断空值用 =NULL → 结果错误
  • 连接顺序错误:跳表连接、主从表颠倒 → 结果不对 / 性能差

  • 三、企业高频面试真题(10 道)

    真题 1:LEFT JOIN 与 INNER JOIN 区别?

    答案: INNER JOIN 只返回两张表交集; LEFT JOIN 保留左表全部数据,右表不匹配补 NULL,是企业最常用连接。

    真题 2:为什么不推荐使用 RIGHT JOIN?

    答案: RIGHT JOIN 逻辑可读性差,所有 RIGHT JOIN 都可以换成 LEFT JOIN,企业统一规范只用 LEFT JOIN,便于维护。

    真题 3:UNION 与 UNION ALL 区别?哪个快?

    答案: UNION 会去重并排序,速度慢; UNION ALL 直接拼接,速度远快于 UNION,生产优先使用。

    真题 4:EXISTS 与 IN 怎么选?

    答案: 小表用 IN,大表关联必用 EXISTS; EXISTS 只判断存在,匹配到即停止,性能更高。

    真题 5:NOT IN 有什么坑?怎么解决?

    答案: 子查询返回 NULL 时,NOT IN 结果永远为空。 必须用 NOT EXISTS 替代。

    真题 6:什么是笛卡尔积?怎么避免?

    答案: 多表连接无关联条件导致全表匹配,数据量爆炸。 避免:每层 JOIN 必须写 ON,用主键 = 外键关联,先过滤再连接。

    真题 7:左连接中,右表条件放 ON 还是 WHERE?

    答案: 右表条件放 ON,不影响左表保留; 放 WHERE 会过滤左表,等价于内连接。

    真题 8:子查询有哪几种类型?

    答案: 按结果分:标量、列、行子查询。 按关键字分:IN/ANY/ALL/EXISTS。

    真题 9:如何查询 “没有下单的用户”?

    答案:

    sql

    SELECT * FROM users u
    WHERE NOT EXISTS (
    SELECT 1 FROM orders o
    WHERE o.user_id=u.user_id
    );

    真题 10:多表连接统计时,为什么要用 COUNT (DISTINCT)?

    答案: 一对多连接会导致行数膨胀,直接 COUNT 会重复计算,必须用 DISTINCT 去重。


    四、综合实战环境(直接复制运行)

    sql

    — 用户表
    CREATE TABLE users (
    user_id INT PRIMARY KEY,
    user_name VARCHAR(20) NOT NULL
    );

    — 订单表
    CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    order_time DATE
    );

    — 商品表
    CREATE TABLE goods (
    goods_id INT PRIMARY KEY,
    goods_name VARCHAR(30),
    price DECIMAL(10,2)
    );

    — 订单明细表
    CREATE TABLE order_item (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_id INT,
    goods_id INT,
    num INT
    );

    INSERT INTO users VALUES (1,'张三'),(2,'李四'),(3,'王五'),(4,'赵六');
    INSERT INTO orders VALUES
    (1001,1,299,'2024-06-01'),
    (1002,2,420,'2024-06-02'),
    (1003,3,88,'2024-06-03');
    INSERT INTO goods VALUES (1,'笔记本',299),(2,'键盘',159),(3,'T恤',99);
    INSERT INTO order_item VALUES (1,1001,1,1),(2,1002,3,1),(3,1003,2,1);


    五、综合实战大题(企业标准难度)

    综合题 1:四表联查 + 统计

    查询所有用户的: 用户名、订单数、商品总数、总消费金额,无消费显示 0。

    sql

    SELECT
    u.user_id,
    u.user_name,
    COUNT(DISTINCT o.order_id) AS order_cnt,
    COALESCE(SUM(oi.num),0) AS total_goods,
    COALESCE(SUM(oi.num * g.price),0) AS total_amount
    FROM users u
    LEFT JOIN orders o ON u.user_id = o.user_id
    LEFT JOIN order_item oi ON o.order_id = oi.order_id
    LEFT JOIN goods g ON oi.goods_id = g.goods_id
    GROUP BY u.user_id, u.user_name
    ORDER BY total_amount DESC;

    综合题 2:子查询 + EXISTS 优化

    查询买过 “笔记本” 的用户(用 EXISTS,性能最优)。

    sql

    SELECT * FROM users u
    WHERE EXISTS (
    SELECT 1 FROM orders o
    JOIN order_item oi ON o.order_id=oi.order_id
    JOIN goods g ON oi.goods_id=g.goods_id
    WHERE o.user_id=u.user_id
    AND g.goods_name='笔记本'
    );

    综合题 3:联合查询 + 报表汇总

    合并订单表,统计: 线上总金额、线下总金额、总金额(模拟两表合并)。

    sql

    SELECT '订单总金额' AS type, SUM(amount) FROM orders
    UNION ALL
    SELECT '商品总销售额' AS type, SUM(num*price)
    FROM order_item oi
    JOIN goods g ON oi.goods_id=g.goods_id;


    六、注意事项(职场终极规范)

  • 主表永远放左边,只用 LEFT JOIN
  • 右表条件放 ON,不要放 WHERE
  • ** 禁止 SELECT ***,只查需要字段
  • 关联字段必须建索引(user_id、order_id、goods_id)
  • 大表用 EXISTS,不用 IN
  • 非存在查询只用 NOT EXISTS
  • 联合查询默认 UNION ALL
  • 统计一对多数据必须用 COUNT (DISTINCT)
  • 判断 NULL 必须用 IS NULL / IS NOT NULL
  • 多层连接不要跳表,逐级 ON 关联

  • 七、核心总结(全文最精华)

  • 连接:内连接取交集,左连接保主表,企业 90% 用 LEFT JOIN
  • 子查询:标量单值、列表用 IN、存在用 EXISTS
  • 优化:大表 EXISTS、非存在 NOT EXISTS、联合 UNION ALL
  • 避坑:笛卡尔积、NULL、NOT IN、跳表连接
  • 能力:三~五表链式连接 + 子查询 + 统计 = 企业中高级 SQL 水平
  • 一句话通关口诀: 左连接为主表全留,子查询 EXISTS 最优;联合用 ALL 速度够,NULL 与笛卡尔积要躲;多表逐级不跳走,职场 SQL 不用愁


    八、下一步学习预告

    从下一篇开始,我们进入企业进阶刚需模块:

    • 事务 ACID
    • 事务隔离级别
    • 窗口函数(面试必考)
    • CTE 公用表表达式
    • 存储过程、触发器
    • 索引优化、EXPLAIN
    赞(0)
    未经允许不得转载:171主机测评 » 重难点复盘|多表 + 子查询真题演练,吃透核心(附面试真题)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址