SQL面试问题解析

随着技术的发展和数据量的增加,对SQL的掌握变得越来越重要。在现代面试中,面试官更关注候选人如何将SQL的基础知识应用于解决实际问题。本文将介绍一些常见的SQL面试问题及其解决方案,帮助在面试中更好地展示技术能力。

SQL简介

SQL(Structured Query Language)是一种用于关系型数据库管理系统(RDBMS)的标准语言,用于与数据库进行交互。自1970年发明以来,SQL已成为维护关系数据库的知名工具,可以创建数据库和表、插入记录、删除记录、查询记录和更新记录等。

数据表示例

在面试中,通常会提供几个数据表以供查询。本文考虑了两个表:“Employee_detail”和“Employee_salary”。第一个表包含了IT员工的基本资料,如ID、姓名、职位、城市和入职日期。第二个表包含了员工的薪资信息,如净收入、变动部分和ID。

以下是Employee_detail表的结构和数据示例:

Row_num | EmpId | FullName | Designation | DateOfJoining | City 1 | 121 | Rachit Tomar | Apprentice | 01/31/2014 | Paris 2 | 321 | Jag Reddy | Developer | 01/30/2015 | New Delhi 3 | 421 | Vasa Trisha | Team Lead | 27/11/2016 | Chennai

以下是Employee_salary表的结构和数据示例:

EmpId | NetPay | Variable 121 | 85000 | 2000 321 | 10000 | 5000 421 | 70000 | 3000

面试问题及解决方案

以下是一些常见的SQL面试问题及其解决方案,这些问题覆盖了从基本查询到更复杂的数据处理技术。

以下是两种找出员工第二高薪资的方法:

-- 使用N-1规则 SELECT DISTINCT NetPay FROM Employee_salary e1 WHERE 1 = (SELECT COUNT(DISTINCT Salary) FROM Employee_salary e2 WHERE e2.NetPay > e1.NetPay); -- 使用max聚合函数 SELECT MAX(NetPay) FROM Employee_salary WHERE NetPay NOT IN (SELECT MAX(NetPay) FROM Employee_salary);

这两种方法都能有效找出第二高的薪资,但实现方式不同。第一种方法通过比较和计数来实现,而第二种方法通过排除最高薪资来找到第二高薪资。

以下是两种查询薪资在60k到95k之间的员工详情的方法:

-- 使用大于和小于操作符 SELECT * FROM Employee_salary WHERE NetPay >= 60000 AND NetPay <= 95000; -- 使用BETWEEN操作符 SELECT * FROM Employee_salary WHERE NetPay BETWEEN 60000 AND 95000;

这两种查询都使用了简单的关系操作符和BETWEEN关键字来检查薪资范围。

以下是两种查询名字不以V、R或S开头的员工详情的方法:

-- 使用NOT操作符 SELECT * FROM Employee_detail WHERE FullName LIKE '[!VRS]%'; -- 使用NOT LIKE操作符 SELECT * FROM Employee_detail WHERE FullName NOT LIKE '[VRS]%';

这两种方法都使用了LIKE关键字进行模式匹配,通过比较FullName字段的第一个字母与V、R、S,如果不匹配,则显示该行。

以下是两种创建新表的方法,一种不包含数据,另一种包含数据:

-- 创建不包含数据的新表 CREATE TABLE Employee_details2 AS SELECT * FROM Employee_detail WHERE 1=2; -- 创建包含数据的新表 CREATE TABLE Employee_details2 AS SELECT * FROM Employee_detail;

这两种方法都使用了AS关键字来引用另一个表,并使用了一个假条件(1=2)来限制新表中的数据输入。

以下是显示Employee_detail表的前50%和后50%记录的方法:

-- 显示前50%记录 SELECT row_num, e1.* FROM Employee_detail e1 WHERE row_num <= (SELECT COUNT(*)/2 FROM Employee_detail); -- 显示后50%记录 SELECT row_num, e1.* FROM Employee_detail e1 MINUS SELECT row_num, e2.* FROM Employee_detail e2 WHERE row_num <= (SELECT COUNT(*)/2 FROM Employee_detail);

这两种查询都使用了COUNT(*)函数来计算总行数,然后使用'/'操作符将它们分成两部分。

以下是两种获取Employee_detail表中唯一记录的方法:

-- 使用DISTINCT关键字 SELECT DISTINCT * FROM Employee_detail; -- 不使用DISTINCT关键字 SELECT * FROM Employee_detail UNION SELECT * FROM Employee_detail;

这两种方法都使用了UNION关键字来比较Employee_detail表与自身,并只打印唯一的记录。

以下是将字符串“SHIKHA”分割成多列的方法:

SELECT SUBSTR('SHIKHA', Level, 1) FROM Dual CONNECT BY Level <= LENGTH('SHIKHA');

这种方法使用了SUBSTR()函数来获取给定字符串的子字符串,Level用于找到列的层次级别,Connect By定义了父子层次关系,Length()函数计算传递的字符串的大小,Dual是Oracle创建的虚拟表。

以下是使用单条查询进行电子邮件验证的方法:

SELECT Email_id FROM Employee_detail WHERE NOT REGEXP_LIKE(Email_id, '[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}', 'i');

这种方法使用了REGEXP_LIKE聚合函数进行电子邮件验证,正则表达式设置了有效电子邮件的规则,LIKE将比较并匹配字符串。

以下是计算并删除Employee_detail表中的重复行的方法:

-- 计算重复行 SELECT EmpId, COUNT(EmpId) FROM Employee_detail GROUP BY EmpId HAVING COUNT(EmpId) > 1 ORDER BY COUNT(EmpId) DESC; -- 删除重复行 DELETE FROM Employee_detail e1 WHERE EmpId = (SELECT MAX(EmpId) FROM Employee_detail e2 WHERE e1.EmpId = e2.EmpId); -- 找出偶数行 SELECT * FROM (SELECT row_num AS rn, Ed.* FROM Employee_detail Ed) WHERE MOD(rn, 2) = 0; -- 找出奇数行 SELECT * FROM (SELECT row_num AS rn, Ed.* FROM Employee_detail Ed) WHERE MOD(rn, 2) = 1;
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485