小牛丨软件测试学习小牛丨软件测试学习
首页
  • 业务测试面试题
  • 数据库测试面试题
  • Linux测试环境面试题
  • 网络协议测试面试题
  • 中间件测试面试题
  • Java测试开发面试题
  • Python测试开发面试题
  • Python自动化面试题
  • Java自动化面试题
  • 性能测试面试题
  • 手撕代码
  • HR面试题
  • 系列总入口
  • 业务测试理论
  • 数据库测试
  • Linux测试环境
  • 网络协议
  • 中间件测试
  • Python编程
  • Java编程
  • 自动化测试
  • 性能测试
  • AI测试
  • HR面试
  • AI测试学习路线
  • AI测试基础面试题
  • 大模型测试面试题
  • AI自动化测开面试题
  • AI Agent测试面试题
  • AI性能与稳定性测试面试题
  • AI应用安全测试面试题
  • 互联网大厂面试真题
  • 互联网中厂面试真题
  • 手机厂商面试真题
  • 通信厂商面试真题
  • 新能源汽车面试真题
  • 银行金融面试真题
  • 项目说明
  • 电商接口文档
  • 实战项目总入口
  • 测试简历编写指南
  • 20K level 简历打磨指南
  • 测试简历模板参考
  • 简历常见问题与避坑
  • 零基础入行专题路径
  • 初中级进阶高级专题路径
  • 零基础小白入行软件测试保姆级学习路线
  • 初中级测试进阶高级测试全路线
首页
  • 业务测试面试题
  • 数据库测试面试题
  • Linux测试环境面试题
  • 网络协议测试面试题
  • 中间件测试面试题
  • Java测试开发面试题
  • Python测试开发面试题
  • Python自动化面试题
  • Java自动化面试题
  • 性能测试面试题
  • 手撕代码
  • HR面试题
  • 系列总入口
  • 业务测试理论
  • 数据库测试
  • Linux测试环境
  • 网络协议
  • 中间件测试
  • Python编程
  • Java编程
  • 自动化测试
  • 性能测试
  • AI测试
  • HR面试
  • AI测试学习路线
  • AI测试基础面试题
  • 大模型测试面试题
  • AI自动化测开面试题
  • AI Agent测试面试题
  • AI性能与稳定性测试面试题
  • AI应用安全测试面试题
  • 互联网大厂面试真题
  • 互联网中厂面试真题
  • 手机厂商面试真题
  • 通信厂商面试真题
  • 新能源汽车面试真题
  • 银行金融面试真题
  • 项目说明
  • 电商接口文档
  • 实战项目总入口
  • 测试简历编写指南
  • 20K level 简历打磨指南
  • 测试简历模板参考
  • 简历常见问题与避坑
  • 零基础入行专题路径
  • 初中级进阶高级专题路径
  • 零基础小白入行软件测试保姆级学习路线
  • 初中级测试进阶高级测试全路线
  • 数据库测试精华文章

    • 数据库测试精华文章
    • 1. 测试工程师为什么必须会数据库
    • 2. SQL 基础查询面试怎么准备
    • 3. 多表关联查询怎么讲清楚
    • 4. group by 和聚合函数怎么用于测试
    • 5. 索引面试怎么回答才不虚
    • 6. 事务 ACID 怎么结合业务理解
    • 7. 数据库锁和并发问题测试怎么讲
    • 8. 接口测试中怎么做数据库断言
    • 9. 常见手撕 SQL 题怎么准备
    • 10. 数据库测试常见问题定位思路
⌕
🛒项目实战📦资料包🛠测试神器AIAI路线CV简历测评🧭入行测评🧪测开测评🎯训练营🏆案例❤赞赏我

9. 常见手撕 SQL 题怎么准备?

手撕 SQL 是测试、测试开发、数据测试、后端接口测试面试中非常常见的环节。很多候选人一听“手撕 SQL”就开始背答案,比如第二高薪资、连续登录、每组 TopN。背题能帮你应付一部分,但真正面试时,表结构稍微变一下、字段名换一下、条件多一条,就容易卡住。

准备手撕 SQL 的正确方式不是死背,而是按题型建立解题框架。你要知道统计类题用 group by,关联类题用 join,去重类题用 distinct 或分组,排名类题可以用窗口函数,连续登录类题要处理日期连续性。面试时还要边写边解释,让面试官知道你的思路,而不是蒙出一个答案。

一、手撕 SQL 面试考什么

手撕 SQL 主要考四种能力:

  1. 是否理解表结构和业务含义;
  2. 是否能把需求翻译成查询条件;
  3. 是否能选择合适的 SQL 结构;
  4. 是否能处理边界和重复数据。

测试岗位的 SQL 题通常不会特别偏数据库底层,而是偏业务查询和数据统计。比如订单表、用户表、登录表、成绩表、薪资表、商品表、支付流水表。

二、答题前先问清楚三件事

1. 表结构是什么

不要急着写 SQL。先确认表名、字段名、主键、关联字段、时间字段、状态字段。

2. 输出结果是什么

要输出用户 ID 还是用户姓名?要输出数量还是明细?要不要排序?要不要去重?

3. 过滤条件是什么

是否只统计有效数据?是否只统计成功支付?是否排除删除数据?时间范围怎么定义?

很多 SQL 写错不是语法问题,而是需求理解错。

三、高频题型 1:查询重复数据

题目:查询手机号重复的用户。

表:t_user(id, mobile, name)。

select mobile, count(*) as cnt
from t_user
group by mobile
having count(*) > 1;

如果要查重复手机号对应的完整用户记录:

select *
from t_user
where mobile in (
  select mobile
  from t_user
  group by mobile
  having count(*) > 1
);

测试场景:注册接口如果没有唯一校验,可能出现重复手机号。这个题能和测试唯一性校验结合起来讲。

四、高频题型 2:查询第二高薪资

表:employee(id, name, salary)。

写法一:去重排序。

select distinct salary
from employee
order by salary desc
limit 1, 1;

如果要查第二高薪资的员工:

select *
from employee
where salary = (
  select distinct salary
  from employee
  order by salary desc
  limit 1, 1
);

注意:如果最高薪有多人,distinct 可以避免把同一薪资重复计算。

五、高频题型 3:每组 TopN

题目:查询每个部门工资最高的 3 名员工。

如果数据库支持窗口函数:

select department_id, name, salary
from (
  select
    department_id,
    name,
    salary,
    row_number() over(partition by department_id order by salary desc) as rn
  from employee
) t
where rn <= 3;

如果要考虑并列,可以用 dense_rank()。

测试场景:排行榜、销量榜、成绩榜、消费金额 TopN 都是类似问题。

六、高频题型 4:按日期统计订单量

表:t_order(order_no, status, create_time)。

select date(create_time) as order_date, count(*) as order_count
from t_order
where create_time >= '2026-04-01 00:00:00'
  and create_time < '2026-05-01 00:00:00'
group by date(create_time)
order by order_date;

如果只统计已支付订单:

select date(pay_time) as pay_date, count(*) as pay_count
from t_order
where status = 'PAID'
  and pay_time >= '2026-04-01 00:00:00'
  and pay_time < '2026-05-01 00:00:00'
group by date(pay_time)
order by pay_date;

测试时要关注:时间边界、状态条件、无数据日期是否补 0。

七、高频题型 5:多表关联统计

题目:统计每个用户的订单数量和消费金额。

表:t_user(id, name),t_order(order_no, user_id, status, total_amount)。

select u.id, u.name, count(o.order_no) as order_count, sum(o.total_amount) as total_amount
from t_user u
left join t_order o on u.id = o.user_id and o.status = 'PAID'
group by u.id, u.name;

这里使用 left join,是为了保留没有订单的用户。如果用 inner join,没有订单的用户会消失。

八、高频题型 6:查询从未下单的用户

select u.id, u.name
from t_user u
left join t_order o on u.id = o.user_id
where o.order_no is null;

这个题本质是 left join 找缺失关联数据。测试中经常用来找有主数据但缺少关联数据的问题。

九、高频题型 7:连续登录用户

表:login_log(user_id, login_date),查询连续 3 天登录用户。

如果支持窗口函数,可以用日期减排名的思路:

select user_id
from (
  select
    user_id,
    login_date,
    date_sub(login_date, interval row_number() over(partition by user_id order by login_date) day) as flag_date
  from (
    select distinct user_id, login_date
    from login_log
  ) t1
) t2
group by user_id, flag_date
having count(*) >= 3;

这类题不要求每个测试都背得滚瓜烂熟,但要理解核心:先去重,再按用户排序,再判断日期是否连续。

十、高频题型 8:查询每个商品销量

表:t_order(status),t_order_item(order_no, product_id, quantity)。

select i.product_id, sum(i.quantity) as sale_count
from t_order o
join t_order_item i on o.order_no = i.order_no
where o.status = 'PAID'
group by i.product_id
order by sale_count desc;

测试场景:商品销量榜、后台商品统计、运营报表。

十一、高频题型 9:查询金额异常订单

题目:订单主表金额不等于明细金额之和。

select o.order_no, o.total_amount, sum(i.price * i.quantity) as item_amount
from t_order o
join t_order_item i on o.order_no = i.order_no
group by o.order_no, o.total_amount
having o.total_amount <> sum(i.price * i.quantity);

这类 SQL 非常有测试价值,可以直接用于发现数据一致性问题。

十二、高频题型 10:分页查询

第一页 10 条:

select order_no, create_time
from t_order
order by create_time desc
limit 0, 10;

第二页 10 条:

select order_no, create_time
from t_order
order by create_time desc
limit 10, 10;

面试可能追问深分页慢的问题。可以回答:数据量大时 offset 很大可能慢,可以考虑限制页数、增加查询条件、使用游标分页等。

十三、面试现场怎么表达

手撕 SQL 时不要沉默写。建议按这个节奏:

  1. 先复述需求;
  2. 确认表结构和输出字段;
  3. 判断是否需要 join;
  4. 判断是否需要 group by;
  5. 判断是否需要排序、去重、窗口函数;
  6. 写 SQL;
  7. 解释边界。

比如题目是“统计每个用户支付成功订单金额”,你可以说:

我先确认订单表里有 user_id、status、total_amount 字段。因为是每个用户,所以要 group by user_id;因为只统计支付成功,所以 where status='PAID';金额用 sum(total_amount)。如果要展示用户名,再关联用户表。

这样即使 SQL 小地方写错,面试官也能看到你的思路。

十四、面试回答模板

如果面试官问“你怎么准备手撕 SQL”,可以这样答:

我会按题型准备,而不是死背单个答案。统计类题重点是 group by、count、sum;关联类题重点是 join 和 left join;去重类题用 distinct 或 group by;排名类题可以用窗口函数;连续登录类题要先去重再判断日期连续。面试现场我会先确认表结构、输出字段和过滤条件,再判断是否需要关联、分组、排序和去重。比如订单金额校验,我会关联订单主表和明细表,用 having 找出主表金额和明细合计不一致的数据。

十五、练习清单

  1. 查询重复手机号;
  2. 查询第二高薪资;
  3. 查询每组 Top3;
  4. 按日期统计订单数;
  5. 统计每个用户消费金额;
  6. 查询从未下单的用户;
  7. 查询连续 3 天登录用户;
  8. 统计每个商品销量;
  9. 查询金额异常订单;
  10. 分页查询订单列表。

手撕 SQL 的核心是题型思维。你只要把常见题型拆清楚,再结合测试业务场景讲出来,面试就不会只是“背 SQL”,而是展示你解决数据问题的能力。

配套刷题:

  • 手撕代码
  • 数据库测试面试题
相关推荐

下一步可以看这些

面试通关软件测试面试通关系列精华文章

把面试题、项目、简历和训练营串成一套求职准备路径。

入行路线零基础入行软件测试专题路径

从测评、学习路线、项目、简历到面试,按顺序入行。

进阶路线初中级测试进阶高级专题路径

接口自动化、性能测试、CI/CD、复杂业务质量保障进阶路线。

AI 方向AI 测试学习路线专题页

大模型评测、RAG 测试、Agent 测试和 AI 自动化路线。

求职结果Offer 案例 / 学员案例展示

看看真实学员 Offer 案例,判断目标和学习投入是否匹配。

资料 / 交流群添加小牛微信

备注:资料、简历、AI 或找工作,领取对应资料或进交流群。

添加小牛微信
Prev
8. 接口测试中怎么做数据库断言
Next
10. 数据库测试常见问题定位思路