SQL 面试题练习

这篇博客主要探讨了如何使用SQL解决复杂的查询问题,包括使用子查询、GROUP BY…HAVING…、删除冗余信息、自连接以及各种条件筛选等。通过一系列面试题实例,解释了如何查询每门课都大于80分的学生、删除重复记录、显示所有比赛组合、筛选发生额高于特定科目的科目、实现多表查询和操作,以及理解触发器、存储过程、索引等数据库概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 用一条SQL 语句 查询出每门课都大于80 分的学生姓名
nameclassscore
张三语文81
张三数学75
李四语文76
李四数学90
王五语文81
王五数学100
王五英语90
  • 答案 1:使用子查询,先选择分数小于等于 80 分的学生姓名,只要姓名不在这里面的,就每门课程都大于 80 分
SELECT DISTINCT name 
FROM table 
WHERE name NOT IN
(SELECT DISTINCT name
FROM table WHERE score<=80);
  • 答案 2:使用 GROUP BY…HAVING…,将分数按姓名分组,选择分组最小分数大于 80 的组的姓名
SELECT name
FROM table
GROUP BY name
HAVING MIN(score)>80;
  1. 删除除了自动编号不同, 其他都相同的学生冗余信息
Noidnameclassscore
10001张三语文81
20003李四数学75
30001张三语文81
  • 答案:按照后面几项进行分组,选取其最小编号作为唯一编号,删除不在唯一编号里的(即后面几项内容重复的),注意 MySQL 中子查询的格式,需指定别名。
DELETE FROM table
WHERE No NOT IN 
(SELECT * 
FROM 
(SELECT MIN(No) 
FROM table
GROUP BY id, name, class, score) A);
  1. 一个叫 team 的表,里面只有一个字段 name, 一共有 4 条纪录,分别是 a, b, c, d, 对应四个球队,现在四个球队进行比赛,用一条 SQL 语句显示所有可能的比赛组合
  • 答案:使用别名,自身比较并组合
SELECT a.name team1, b.name team2
FROM team a, team b
WHERE a.name<b.name
  1. 请用 SQL 语句实现:从 table 数据表中查询出所有月份的发生额都比 101 科目相应月份的发生额高的科目。table 中有很多科目,都有1-12 月份的发生额。字段分别为:
    no :科目代码,mon :发生额月份,num :发生额
  • 答案:先将 101 科目的数据拎出来,作为 b 表,然后提取出原数据表中月份和 b 表相同,发生额比 b 表大的数据,作为 c 表,然后对 c 表中按科目分类计数,结果为 12 个月的即为最终结果
SELECT c.* FROM
(SELECT a.* FROM table a, (SELECT * FROM table WHERE no=101) b
WHERE a.mon=b.mon AND a.num>b.num) c
GROUP BY c.no HAVING COUNT(c.mon)=12
  1. 面试题:怎么把这样一个表
yearmonthamount
199111.1
199121.2
199131.3
199141.4
199212.1
199222.2
199232.3
199242.4

查成这样一个结果

yearm1m2m3m4
19911.11.21.31.4
19922.12.22.32.4
  • 答案:按 year 分组,分别选取月数等于1,2,3,4,且年等于分组年的数据
SELECT year,
(SELECT amount FROM table m WHERE month=1 AND m.year=table.year) m1,
(SELECT amount FROM table m WHERE month=2 AND m.year=table.year) m2,
(SELECT amount FROM table m WHERE month=3 AND m.year=table.year) m3,
(SELECT amount FROM table m WHERE month=4 AND m.year=table.year) m4
FROM table
GROUP BY year;
  1. 只复制表的结构:利用 WHERE 限制添加数据
 SELECT * INTO b FROM a WHERE 1<>1;  
  1. 显示文章、提交人和最后回复时间:
SELECT a.title, a.name, b.adddate FROM 
table a, (SELECT MAX(adddate) adddate FROM table WHERE table.title=a.title) b;
SELECT a.title, a.name, b.adddate FROM 
table a, (SELECT MAX(adddate) adddate FROM table GROUP BY title) b;
  1. 日程安排提前五分钟提醒:
SELECT * FROM 日程安排 WHERE DATEDIFF('mi', GETDATE(), 开始时间) <= 5; 
  1. 有两个表A 和B ,均有 key 和 value 两个字段,如果 B 的 key 在A 中也有,就把 B 的 value 换为 A 中对应的 value,注意要添加中间层 t 避免出现错误(You can’t specify target table ‘B’ for update in FROM clause):
UPDATE B
SET value=(SELECT A.value FROM A WHERE A.key=B.key)
WHERE B.key IN
(SELECT t.key
FROM
(SELECT B.key FROM B, A WHERE B.key=A.key) t);
  1. 成绩分类,原表:
idnamescore
1Java70
2oracle90
3xml40
4jsp30
5servlet80

结果显示是否及格:

idnamescoremark
1Java70Pass
2oracle90Pass
3xml40Fail
4jsp30Fail
5servlet80Pass
SELECT id, name, score,
(CASE WHEN score>=60 THEN 'Pass' ELSE 'Fail' END) AS mark 
FROM course;
  1. 表1:
iddepartment
1设计
2市场
3售后

表 2:

iddptIDname
11张三
21李四
32王五
43彭六
54陈七

用一条SQL语句,显示如下结果

iddptIDdepartmentname
11设计张三
21设计李四
32市场王五
43售后彭六
54黑人陈七

答案:注意 SQL Server 中是 ISNULL(department, ‘黑人’),MySQL 中是 IFNULL(department, ‘黑人’),MySQL 中 ISNULL 只有一个参数,返回 0 或 1;

SELECT testtable2.* , IFNULL(department,'黑人')
FROM testtable1 RIGHT JOIN testtable2 ON testtable2.dptID = testtable1.id
  1. 有表 A,结构如下:
p_IDp_Nums_ID
11001
11202
2801
31101
3803

其中:p_ID为产品ID,p_Num为产品库存量,s_id为仓库ID。请用SQL语句实现将上表中的数据合并,合并后的数据为:

p_IDs1_IDs2_IDs3_ID
110120
2800
31108

其中:s1_ID为仓库1的库存量,s2_ID为仓库2的库存量,s3_ID为仓库3的库存量。如果该产品在某仓库中无库存量,那么就是0代替。

答案1:按 p_ID 分组

SELECT p_ID,
SUM(CASE WHEN s_ID=1 THEN p_Num ELSE 0 END) AS s1_ID,
SUM(CASE WHEN s_ID=2 THEN p_Num ELSE 0 END) AS s2_ID,
SUM(CASE WHEN s_ID=3 THEN p_Num ELSE 0 END) AS s3_ID
FROM A GROUP BY p_ID;

答案2:按 s_ID 分组

SELECT p_ID,
(SELECT SUM(p_Num) FROM A a WHERE s_ID=1 AND a.p_ID = A.p_ID) AS s1_ID,
(SELECT SUM(p_Num) FROM A a WHERE s_ID=2 AND a.p_ID = A.p_ID) AS s2_ID,
(SELECT SUM(p_Num) FROM A a WHERE s_ID=3 AND a.p_ID = A.p_ID) AS s3_ID
FROM A GROUP BY s_ID;
  1. 触发器的作用?
    :触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。

  2. 什么是存储过程?用什么来调用?
    :存储过程是一个预编译的SQL 语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL ,使用存储过程比单纯SQL 语句执行要快。可以用一个命令对象来调用存储过程。

  3. 索引的作用?和它的优点缺点是什么?
    :索引就是一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。

  4. 什么是内存泄漏?
    :一般我们所说的内存泄漏指的是堆内存的泄漏。堆内存是程序从堆中为其分配的,大小任意的,使用完后要显示释放内存。当应用程序用关键字 new 等创建对象时,就从堆中为它分配一块内存,使用完后程序调用 free 或者 delete 释放该内存,否则就说该内存就不能被使用,我们就说该内存被泄漏了。

  5. 维护数据库的完整性和一致性,你喜欢用触发器还是自写业务逻辑?为什么?
    :我是这样做的,尽可能使用约束,如check, 主键,外键,非空字段等来约束,这样做效率最高,也最方便。其次是使用触发器,这种方法可以保证,无论什么业务系统访问数据库都可以保证数据的完整新和一致性。最后考虑的是自写业务逻辑,但这样做麻烦,编程复杂,效率低下。

  6. 什么是事务?什么是锁?
    事务就是被绑定在一起作为一个逻辑工作单元的 SQL 语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过 ACID 测试,即原子性,一致性,隔离性和持久性。 :在所有的 DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。

  7. 什么叫视图?游标是什么?
    视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。游标:是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。

  8. 为管理业务培训信息,建立3个表:
    S:S#,SN,SD,SA,分别代表学号,学员姓名,所属单位,学员年龄
    C:C#,CN,分别代表课程编号,课程名称
    SC:S#,C#,G,分别代表学号,所选的课程编号,学习成绩

(1) 使用标准 SQL 嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名?

SELECT S#, SN FROM S 
WHERE S# IN (SELECT S# FROM SC, C WHERE SC.C#=C.C# AND C.CN='税收基础');

(2) 使用标准 SQL 嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位?

SELECT SN, SD FROM S
WHERE S# IN (SELECT S# FROM SC WHERE C#='C2');
# 或者
SELECT SN, SD FROM S, SC
WHERE S.S#=SC.S# AND SC.C#='C2';

(3) 使用标准 SQL 嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位?

SELECT SN, SD FROM S 
WHERE S# NOT IN (SELECT S# FROM SC WHERE C#='C5');

(4) 查询选修了课程的学员人数

SELECT COUNT(DISTINCT S#) AS 学员人数 FROM SC;

(5) 查询选修课程超过 5 门的学员学号和所属单位?

SELECT SN, SD FROM S 
WHERE S# IN 
(SELECT S# FROM SC
GROUP BY S#
HAVING COUNT(DISTINCT C#) > 5);
  1. 查询 A(ID,Name) 表中第31至40条记录:
# MySQL:
SELECT * FROM A LIMIT 30, 40;

# SQL Server:
SELECT * FROM (SELECT TOP 40 * FROM A) aa
WHERE NOT EXISTS (SELECT * FROM (SELECT TOP 5 * FROM A) bb
WHERE aa.ID=bb.ID);
  1. 查询表 A 中存在 ID 重复三次以上的记录:
SELECT * FROM (SELECT COUNT(ID) AS count FROM A GROUP BY ID) T WHERE T.count>3;
  1. NULL是什么意思?
    :NULL这个值表示UNKNOWN(未知):它不表示“”(空字符串)。假设您的SQL Server数据库里有ANSI_NULLS,当然在默认情况下会有,对NULL这个值的任何比较都会生产一个NULL值。您不能把任何值与一个 UNKNOWN值进行比较,并在逻辑上希望获得一个答案。您必须使用IS NULL操作符。

  2. 什么是索引?SQL Server 2000里有什么类型的索引?
    :简单地说,索引是一个数据结构,用来快速访问数据库表格或者视图里的数据。在SQL Server里,它们有两种形式:聚集索引和非聚集索引。聚集索引在索引的叶级保存数据。这意味着不论聚集索引里有表格的哪个(或哪些)字段,这些字段都会按顺序被保存在表格。由于存在这种排序,所以每个表格只会有一个聚集索引。非聚集索引在索引的叶级有一个行标识符。这个行标识符是一个指向磁盘上数据的指针。它允许每个表格有多个非聚集索引。

  3. 什么是主键?什么是外键?
    :主键是表格里的(一个或多个)字段,只用来定义表格里的行;主键里的值总是唯一的。外键是一个用来建立两个表格之间关系的约束。这种关系一般都涉及一个表格里的主键字段与另外一个表格(尽管可能是同一个表格)里的一系列相连的字段。那么这些相连的字段就是外键。

  4. 什么是触发器?SQL Server 2000有什么不同类型的触发器?
    :触发器是一种专用类型的存储过程,它被捆绑到 SQL Server 2000 的表格或者视图上。在SQL Server 2000里,有 INSTEAD-OF 和 AFTER 两种触发器。INSTEAD-OF 触发器是替代数据操控语言(Data Manipulation Language,DML)语句对表格执行语句的存储过程。例如,如果我有一个用于 TableA 的 INSTEAD-OF-UPDATE 触发器,同时对这个表格执行一个更新语句,那么 INSTEAD-OF-UPDATE 触发器里的代码会执行,而不是我执行的更新语句则不会执行操作。AFTER触发器要在DML语句在数据库里使用之后才执行。这些类型的触发器对于监视发生在数据库表格里的数据变化十分好用。

  5. 您如何确定一个带有名为 Fld1 字段的 TableB 表格里只具有 Fld1 字段里的那些值,而这些值同时在名为 TableA 的表格的 Fld1 字段里?
    :这个与关系相关的问题有两个可能的答案。第一个答案(而且是您希望听到的答案)是使用外键限制。外键限制用来维护引用的完整性。它被用来确保表格里的字段只保存有已经在不同的(或者相同的)表格里的另一个字段里定义了的值。这个字段就是候选键(通常是另外一个表格的主键)。另外一种答案是触发器。触发器可以被用来保证以另外一种方式实现与限制相同的作用,但是它非常难设置与维护,而且性能一般都很糟糕。由于这个原因,微软建议开发人员使用外键限制而不是触发器来维护引用的完整性。

  6. 对一个投入使用的在线事务处理表格有过多索引需要有什么样的性能考虑?
    :对一个表格的索引越多,数据库引擎用来更新、插入或者删除数据所需要的时间就越多,因为在数据操控发生的时候索引也必须要维护。

  7. 你可以用什么来确保表格里的字段只接受特定范围里的值?
    :这个问题可以用多种方式来回答。您希望听到的回答是 Check 限制,它在数据库表格里被定义,用来限制输入该列的值。触发器也可以被用来限制数据库表格里的字段能够接受的值,但是这种办法要求触发器在表格里被定义,这可能会在某些情况下影响到性能。因此,微软建议使用Check限制而不是其他的方式来限制域的完整性。

  8. 什么是相关子查询?如何使用这些查询?
    :相关子查询是一种包含子查询的特殊类型的查询。查询里包含的子查询会真正请求外部查询的值,从而形成一个类似于循环的状况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值