SQL 大厂面试题目(由浅入深)

今天给大家带来一份大厂SQL面试覆盖:基础语法 → 复杂查询 → 性能优化 → 架构设计,大家需深入理解执行原理并熟悉实际业务场景的解决方案。



1. 基础查询与过滤

题目:查询 employees 表中所有薪资(salary)大于 10000 且部门编号(dept_id)为 5 的员工姓名(name)和入职日期(hire_date)。

sql 复制代码
SELECT name, hire_date 
FROM employees 
WHERE salary > 10000 AND dept_id = 5;

2. 聚合函数与分组

题目:统计每个部门(dept_id)的平均薪资,并仅显示平均薪资高于 15000 的部门。

sql 复制代码
SELECT dept_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY dept_id
HAVING AVG(salary) > 15000;

3. 多表连接(JOIN)

题目:查询员工姓名(name)及其所属部门名称(dept_name),表结构为 employees(id, name, dept_id)和 departments(id, dept_name)。

sql 复制代码
SELECT e.name, d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.id;

4. 子查询与 EXISTS

题目:查询没有订单的客户(customers 表的 id 不在 orders 表的 customer_id 中)。

sql 复制代码
SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.id
);

5. 窗口函数

题目:查询每个部门薪资排名前 3 的员工姓名和薪资。

sql 复制代码
WITH ranked_employees AS (
    SELECT 
        name, salary, dept_id,
        RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rank
    FROM employees
)
SELECT name, salary, dept_id
FROM ranked_employees
WHERE rank <= 3;

6. 递归查询(CTE)

题目:查询树形结构表 categories(id, name, parent_id)中 ID=5 的所有子节点。

sql 复制代码
WITH RECURSIVE sub_categories AS (
    SELECT id, name, parent_id
    FROM categories
    WHERE id = 5
    UNION ALL
    SELECT c.id, c.name, c.parent_id
    FROM categories c
    JOIN sub_categories sc ON c.parent_id = sc.id
)
SELECT * FROM sub_categories;

7. 索引优化

题目:在 orders 表中,如何为 customer_id 和 order_date 设计联合索引以优化查询 WHERE customer_id = 100 AND order_date > '2024-02-10'?

答案:

sql 复制代码
CREATE INDEX idx_customer_order_date ON orders (customer_id, order_date);

**原理:**联合索引按最左前缀匹配原则,优先按 customer_id 过滤,再按 order_date 范围查询。


8. 事务与隔离级别

题目:解释"不可重复读"(Non-Repeatable Read)和"幻读"(Phantom Read)的区别。

答案:

**不可重复读:**同一事务中两次读取同一行数据,结果不同(由其他事务的 UPDATE 或 DELETE 导致)。

**幻读:**同一事务中两次查询同一范围的数据,结果行数不同(由其他事务的 INSERT 导致)。


9. 执行计划分析

题目:以下查询的执行计划中出现了 Full Table Scan,如何优化?

SELECT * FROM products WHERE category = 'Electronics' AND price > 1000;

答案:
添加联合索引 (category, price):

sql 复制代码
CREATE INDEX idx_category_price ON products (category, price);

10. 复杂场景设计

题目:设计一个数据库表结构,支持用户每日签到(可重复签到但仅第一次有效),并统计某用户最近 30 天的签到次数。

答案:

sql 复制代码
CREATE TABLE user_checkins (
    user_id INT,
    checkin_date DATE,
    PRIMARY KEY (user_id, checkin_date) -- 唯一约束避免重复
);

-- 统计最近30天签到次数
SELECT COUNT(*) 
FROM user_checkins 
WHERE user_id = 100 
AND checkin_date >= CURRENT_DATE - INTERVAL '30 days';

11. 死锁分析与解决

题目:两个事务分别执行以下操作,如何发生死锁?

事务1:UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2;

事务2:UPDATE accounts SET balance = balance - 200 WHERE id = 2; UPDATE accounts SET balance = balance + 200 WHERE id = 1;

答案:

事务1锁定id=1后等待id=2,事务2锁定id=2后等待id=1,形成循环等待。

**解决方案:**按固定顺序更新(如先更新id小的账户)。


12. 时间窗口统计

题目:统计每小时内订单量最多的前3个小时(表 orders 含字段 order_time)。

sql 复制代码
WITH hourly_orders AS (
    SELECT 
        EXTRACT(HOUR FROM order_time) AS hour,
        COUNT(*) AS order_count
    FROM orders
    GROUP BY EXTRACT(HOUR FROM order_time)
)
SELECT hour, order_count
FROM hourly_orders
ORDER BY order_count DESC
LIMIT 3;

13. 数据去重

题目:删除 logs 表中重复记录(保留id最小的一条)。

sql 复制代码
DELETE FROM logs
WHERE id NOT IN (
    SELECT MIN(id)
    FROM logs
    GROUP BY user_id, log_time, content
);

14. 分页查询优化

题目:优化大表的分页查询 SELECT * FROM users ORDER BY id LIMIT 1000000, 10;。

答案:
使用覆盖索引 + 游标分页:

sql 复制代码
SELECT * FROM users 
WHERE id > 1000000 
ORDER BY id 
LIMIT 10;

15. 分区表设计

题目:如何按时间范围对 sales 表进行分区以优化查询性能?

答案:

sql 复制代码
-- 按月分区(以 PostgreSQL 为例)
CREATE TABLE sales (
    sale_id SERIAL,
    sale_date DATE,
    amount NUMERIC
) PARTITION BY RANGE (sale_date);

CREATE TABLE sales_2023_01 PARTITION OF sales
    FOR VALUES FROM ('2024-01-10') TO ('2024-02-10');

16. JSON 数据处理

题目:从 products 表的 attributes(JSON 字段)中提取颜色(color)和尺寸(size)。

sql 复制代码
-- 以 MySQL 为例
SELECT 
    attributes->>'$.color' AS color,
    attributes->>'$.size' AS size
FROM products;

17. 高级窗口函数

题目:计算每个员工薪资与所在部门平均薪资的差值。

sql 复制代码
SELECT 
    name,
    salary,
    salary - AVG(salary) OVER (PARTITION BY dept_id) AS diff_from_avg
FROM employees;

18. 动态SQL与存储过程

题目:编写存储过程,根据输入的城市名动态查询 customers 表。

sql 复制代码
-- 以 PostgreSQL 为例
CREATE OR REPLACE PROCEDURE get_customers_by_city(city_name TEXT)
LANGUAGE plpgsql
AS $$
BEGIN
    EXECUTE 'SELECT * FROM customers WHERE city = $1' USING city_name;
END;
$$;

19. 分布式ID生成方案

题目:在分布式系统中,如何设计全局唯一的订单ID?

答案:

雪花算法(Snowflake):时间戳 + 机器ID + 序列号。

UUID:随机生成,但存储效率低。

数据库分段分配:中央数据库分配ID范围给各节点。


20. 数据一致性保障

题目:如何实现"扣减库存时防止超卖"?

答案:

sql 复制代码
-- 事务内原子操作(以 MySQL 为例)
START TRANSACTION;
SELECT stock FROM products WHERE id = 100 FOR UPDATE;
UPDATE products SET stock = stock - 1 WHERE id = 100 AND stock > 0;
COMMIT;
相关推荐
我是个假程序员2 分钟前
sql server数据库可疑修复
数据库
极限实验室2 小时前
如何使用 Nginx 代理 Easysearch 服务
数据库·nginx
whn19772 小时前
selectdb修改表副本
数据库
无情白2 小时前
k8s运维面试总结(持续更新)
运维·面试·kubernetes
TDengine (老段)2 小时前
TDengine 中的视图
数据库·物联网·oracle·时序数据库·tdengine·iotdb
ylfhpy2 小时前
Java面试黄金宝典33
java·开发语言·数据结构·面试·职场和发展·排序算法
Kyrie_Li3 小时前
Redis-Sentinel(哨兵模式)
数据库·redis·sentinel
拉不动的猪3 小时前
uniapp与React Native/vue 的简单对比
前端·vue.js·面试
计算机毕设定制辅导-无忧学长4 小时前
TDengine 数据写入优化:协议选择与批量操作(一)
网络·数据库·tdengine
Mr.洛 白4 小时前
OpenEuler/CentOS一键部署OpenGauss数据库教程(脚本+视频)
数据库·opengauss·gaussdb·国产数据库安装·安装脚本