2025年启用的20个SQL面试问题(附实例)

SQL问题几乎在任何数据分析面试中都有。但是,仅仅能阅读语法是不够的,我们需要知道这些查询是如何工作的,以及为什么。在这篇文章中, 我将分享我在2025年启用的 SQL 面试题库,并提供示例和实用技巧,希望大家有所帮助。

1. 检测表中的重复项

SELECT column1, column2, COUNT(*) AS count 
FROM your_table
GROUP BY column1, column2 
HAVING COUNT(*) > 1;

2. INNER JOIN 和 OUTER JOIN 区别

  • INNER JOIN =交集(仅匹配数据);
  • OUTER JOIN =联合 + NULL (匹配 + 不匹配的数据)
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d 
ON e.department_id = d.department_id;
SELECT e.name, d.department_name 
FROM employees e
LEFT JOIN departments d 
ON e.department_id = d.department_id;

3.第二高的薪水

SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
SELECT MAX(salary) 
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);

4.GROUP BY和HAVING

  • 使用 GROUP BY 对数据进行分组,使用 HAVING 过滤聚合结果。
  • HAVING 在聚合后进行过滤。WHERE 过滤原始行。
SELECT department_id, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5;

5. 收入高于其经理的员工

SELECT e.name AS employee_name, e.salary, 
	m.name AS manager_name, m.salary AS manager_salary
FROM employees e
JOIN employees m 
ON e.manager_id = m.emp_id 
WHERE e.salary > m.salary;

6. 窗口函数

  • 窗口函数对与当前行相关的一组表行执行计算,而不会像 GROUP BY 那样折叠行。
  • 句法:FUNCTION_NAME() OVER(PARTITION BY 列 ORDER BY 列);
  • ROW_NUMBER() 为分区内的每一行分配唯一的序列号;
  • RANK() 将相同的排名分配给具有相同值的行,但跳过下一个排名; 如果 2 名员工的工资相同,则两者都获得排名 1,而下一个员工获得排名 3。
SELECT name, department, salary, 
	ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num 
FROM employees;
SELECT name, department, salary, 
	RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank_num 
FROM employees;

7. 表现最好的3款产品

SELECT product_id, product_name, total_sales 
FROM sales_data
ORDER BY total_sales DESC LIMIT 3;
SELECT product_id, product_name, total_sales 
FROM (
	SELECT *, RANK() OVER (ORDER BY total_sales DESC) AS rank_num 
	FROM sales_data
) ranked_sales
WHERE rank_num <= 3;

8.UNION和UNION ALL之间的区别

  • 快速规则:UNION = distinct;UNION ALL = all
SELECT city FROM customers 
UNION
SELECT city FROM vendors;
SELECT city FROM customers 
UNION ALL
SELECT city FROM vendors;

9.CASE 语句

SELECT name, salary, 
	CASE WHEN salary >= 100000 THEN 'High' 
    	WHEN salary >= 50000 THEN 'Medium' 
    	ELSE 'Low'
	END AS salary_category 
FROM employees;

10. 计算销售的累计总和

  • SUM(…) OVER(…) 根据订单日期计算每个产品的累计总数
  • PARTITION BY 按产品分组,ORDER BY 确保累积遵循时间顺序
SELECT date, product, sales,
	SUM(sales) OVER (PARTITION BY product ORDER BY date) AS sum_sales
FROM sales_details;

11. CTE(通用表表达式)

  • 主要是提高可读性并简化复杂的子查询或递归逻辑
  • 可重用且可读,避免重复子查询
WITH TopEarners AS ( 
  SELECT emp_id, name, salary 
  FROM employees
  WHERE salary > 100000
)

SELECT * 
FROM TopEarners;

12. 多次进行超过10,000块交易的客户

SELECT customer_id, COUNT (*) AS high_trans 
FROM Transactions 
WHERE transaction_amount >  10000  
GROUP  BY customer_id 
HAVING  COUNT (*) >  1 ;

13. DELETE和TRUNCATE之间的区别

  • delete删除where条件中的记录;truncate删除所有的记录(无需where)

14.如何优化 SQL

  • 仅使用 SELECT 查询所需的列
  • 对 JOIN、WHERE、ORDER BY 中经常使用的列创建适当的索引
  • 避免在索引列上使用函数
  • 使用 EXISTS 代替 IN(用于子查询),EXISTS(更适合大型数据集)
  • 避免不必要的连接或嵌套子查询
  • 使用适当的数据类型并避免隐式转换

15. 过去6个月内没有进行任何购买的所有客户

SELECT c.customer_id, c.name 
FROM customers c
LEFT JOIN transactions t
ON c.customer_id = t.customer_id
AND t.transaction_date >= CURRENT_DATE - INTERVAL '6 months' 
WHERE t.customer_id IS NULL;

16. 如何处理 NULL 值

  • 使用 IS NULL / IS NOT NULL
  • 使用 COALESCE() 或 IFNULL() 替换 NULL
  • 处理聚合中的 NULL(例如 AVG、SUM)
  • 条件检查

17. 将行转置为列

SELECT region,
  SUM(CASE WHEN month = 'Jan' THEN sales_amount ELSE 0 END) AS Jan,
  SUM(CASE WHEN month = 'Feb' THEN sales_amount ELSE 0 END) AS Feb,
  SUM(CASE WHEN month = 'Mar' THEN sales_amount ELSE 0 END) AS Mar
FROM sales GROUP BY region;
SELECT region, [Jan], [Feb], [Mar]
FROM (
  SELECT region, month, sales_amount FROM sales
  ) AS src
PIVOT (
  SUM(sales_amount)
  FOR month IN ([Jan], [Feb], [Mar])
) AS p;

18.索引如何提高效率,使用时需要注意什么

  • 创建索引: CREATE INDEX idx_customer_id ON transactions(customer_id);
  • 索引以额外的空间和写入时间性能为代价来提高数据库表上数据检索操作的速度
  • 索引太多会减慢 INSERT/UPDATE 的速度
  • 需要避免对基数较低的列进行索引(例如性别)

19. 每个客户的最大交易金额

SELECT customer_id, MAX(amount) AS max_transaction 
FROM transactions
GROUP BY customer_id;

20.自连接

SELECT e.name AS employee_name, m.name AS manager_name 
FROM employees e
LEFT JOIN employees m
ON e.manager_id = m.emp_id;

我是钱德勒(chandler_is_dreaming),拥有超10年全球顶尖企业数据运营与商业分析实战经验,曾任职于多家头部互联网及国际知名企业,历任商业运营总监、商业智能负责人、数据分析高级经理等职。具备丰富的数据分析实战经验,曾成功从0搭建团队、优化流程、推动数字化转型,最多管理60余人的数据团队,累计面试超300人,尤其擅长数据相关岗位(如数据分析师、商业分析师、运营分析师、数据产品经理等)的职业规划、简历优化、技能提升、业务思维、面试技巧等。

钱德勒,拥有超10年全球顶尖企业数据运营与商业分析实战经验,曾任职于Amazon等国际头部企业,历任商业运营总监、商业智能负责人、数据分析高级经理等职。具备丰富的数据分析实战经验,曾成功从0搭建团队、优化流程、推动数字化转型,管理60余人的数据团队,累计面试超300人,尤其擅长数据相关岗位(如数据分析师、商业分析师、运营分析师、数据产品经理等)的职业规划、简历优化、技能提升、业务思维、面试技巧等。

全部评论

相关推荐

评论
1
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务