联表、分页、聚合函数与索引的基础用法。
未标记
考查重点:结果粒度与连接、聚合、分页。先确定结果一行代表什么,再用 JOIN 关联、GROUP BY 汇总、稳定 ORDER BY 分页;检查连接放大是否重复计数
本题目录
参考答案
本答案基于相关资料,由 AI 辅助编写,供学习与面试准备参考。如有疏漏,欢迎反馈指正。
核心回答
联表按关联键组合数据,分页限制一次返回的记录,聚合函数按分组汇总,索引则帮助减少过滤、连接和排序的访问成本。写SQL先明确结果的一行代表什么,再选择JOIN、GROUP BY和稳定排序,避免联表放大行数后把统计或分页算错。
联表与聚合例子
假设用户表users含id和name,订单表orders含id、user_id和amount。下列查询保留没有订单的用户,统计订单数和总额:
SELECT u.id, u.name, COUNT(o.id) AS order_count,
COALESCE(SUM(o.amount), 0) AS total_amount
FROM users AS u
LEFT JOIN orders AS o ON o.user_id = u.id
GROUP BY u.id, u.name
ORDER BY u.id;
LEFT JOIN保留左表,未匹配右表列为NULL;因此统计订单用COUNT(o.id),不能用COUNT(*)把无订单用户也计作一单。WHERE在分组前过滤行,HAVING过滤聚合后的组;给右表条件放到WHERE时,还要检查是否意外排除了未匹配用户。
分页与索引
分页要有确定顺序。若创建时间可能相同,增加唯一ID作为第二排序键:
SELECT id, user_id, amount
FROM orders
ORDER BY created_at DESC, id DESC
LIMIT 2;
深OFFSET仍需跳过很多记录,连续浏览更适合基于上一页排序键的游标。联表前后的分页粒度要一致,例如按订单分页时,不应先与订单明细展开后直接限制明细行数。
orders.user_id上的合适索引可帮助按用户关联,过滤和排序的联合索引要按实际查询设计。最终用执行计划核对访问顺序、扫描与排序;GROUP BY并不保证输出顺序,想排序应明确ORDER BY。
参考资料
- 国内:shockerli / JavaGuide收录:一千行MySQL学习笔记:借鉴 SELECT、连接与分组子句的整理,解释正文查询中 WHERE、GROUP BY 与 HAVING 的分工。
- 国内:JavaGuide / Snailclimb:MySQL 索引详解:参考索引减少扫描与写入、空间成本的比较,说明正文围绕实际关联、过滤和排序需求设计索引的依据。
- 国内:JavaGuide / Snailclimb:MySQL 执行计划分析:执行计划的估算与实际行数、耗时说明如何验证索引是否服务目标查询。
- 国外:MySQL / Oracle:JOIN Clause:左连接补NULL和ON/WHERE的区别说明保留无订单用户时应如何组织条件。
- 国外:MySQL / Oracle:Aggregate Function Descriptions:COUNT表达式跳过NULL以及SUM空结果的行为说明统计订单数和默认金额的写法。