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

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人,尤其擅长数据相关岗位(如数据分析师、商业分析师、运营分析师、数据产品经理等)的职业规划、简历优化、技能提升、业务思维、面试技巧等。

相关推荐