没问题,这套“SQL面试题经典50例”堪称数据岗位的“必刷题库”。为了帮你高效备考,我基于经典的**学生-课程-成绩**数据库模型,为你精选了4个核心维度的代表性题目(包含代码示例),涵盖了从基础查询到高级分析的高频考点:
---
### 📚 经典SQL 50题(精选解析)
#### 🧱 基础查询与排序
**1. 查询“01”课程比“02”课程成绩高的所有学生的学号**
- **考察点**:自连接、数值比较。
- **逻辑**:将成绩表自连接,分别视为课程01和课程02的成绩,筛选出课程01分数更高的记录。
```
```sql
SELECT a.学号
FROM (SELECT * FROM 成绩表 WHERE 课程号 = '01') a
JOIN (SELECT * FROM 成绩表 WHERE 课程号 = '02') b ON a.学号 = b.学号
WHERE a.成绩 > b.成绩;
```
```
**2. 查询平均成绩大于60分的同学的学号和平均成绩**
- **考察点**:分组聚合 `GROUP BY` 与分组筛选 `HAVING`。
- **注意**:必须使用 `HAVING` 而不是 `WHERE` 来过滤聚合函数结果。
```
```sql
SELECT 学号, AVG(成绩) AS 平均成绩
FROM 成绩表
GROUP BY 学号
HAVING AVG(成绩) > 60;
```
```
#### 🔗 多表连接查询
**3. 查询所有同学的学号、姓名、选课数、总成绩**
- **考察点**:左连接 `LEFT JOIN` 与聚合函数。
- **逻辑**:以学生表为主表,左连接成绩表,即使学生没选课也要显示(此时选课数为0,总成绩为NULL,可用IFNULL处理)。
```
```sql
SELECT s.学号, s.姓名, COUNT(sc.课程号) AS 选课数, SUM(sc.成绩) AS 总成绩
FROM 学生表 s
LEFT JOIN 成绩表 sc ON s.学号 = sc.学号
GROUP BY s.学号, s.姓名;
```
```
**4. 查询没学过“孟扎扎”老师任任何课的同学的姓名**
- **考察点**:三表连接 + `NOT IN` / `NOT EXISTS`。
- **逻辑**:先找出孟扎扎老师教过的所有课程的学生,再取反。
```
```sql
SELECT 姓名
FROM 学生表
WHERE 学号 NOT IN (
SELECT DISTINCT sc.学号
FROM 成绩表 sc
JOIN 课程表 c ON sc.课程号 = c.课程号
JOIN 教师表 t ON c.教师号 = t.教师号
WHERE t.教师姓名 = '孟扎扎'
);
```
```
#### 📊 高级聚合与分组
**5. 查询各科成绩最高分、最低分和平均分**
- **考察点**:分组统计、流程控制函数 `CASE WHEN`。
- **需求**:需显示:课程ID,课程name,选修人数,最高分,最低分,平均分,及格率(>=60),中等率(>=70),优良率(>=80),优秀率(>=90)。
```
```sql
SELECT
c.课程号,
c.课程名称,
COUNT(sc.学号) AS 选修人数,
MAX(sc.成绩) AS 最高分,
MIN(sc.成绩) AS 最低分,
AVG(sc.成绩) AS 平均分,
-- 使用SUM(CASE WHEN)计算占比
SUM(CASE WHEN sc.成绩 >= 60 THEN 1 ELSE 0 END) / COUNT(sc.学号) AS 及格率
FROM 课程表 c
LEFT JOIN 成绩表 sc ON c.课程号 = sc.课程号
GROUP BY c.课程号, c.课程名称;
```
```
#### 🏆 窗口函数(重点难点)
**6. 按各科成绩从高到低进行排名 (允许并列且占用名额)**
- **考察点**:窗口函数 `RANK()` / `DENSE_RANK()` / `ROW_NUMBER()` 的区别。
- **RANK()**:跳跃排序,如有两个第一,则下一个为第三名。
- **DENSE_RANK()**:连续排序,如有两个第一,则下一个为第二名。
```
```sql
SELECT
学号,
课程号,
成绩,
RANK() OVER (PARTITION BY 课程号 ORDER BY 成绩 DESC) AS 排名
FROM 成绩表;
```
```
**7. 查询学生的总成绩并进行排名**
- **考察点**:先聚合(SUM)再排序。
```
```sql
SELECT
学号,
SUM(成绩) AS 总分,
RANK() OVER (ORDER BY SUM(成绩) DESC) AS 总分排名
FROM 成绩表
GROUP BY 学号;
```
```
---
### 💡 面试必背核心考点总结
| 考点 | 关键词 | 注意事项 |
| ------ |------ |------ |
| **连接** | `INNER JOIN`, `LEFT JOIN` | 区分主表与从表,`ON` 后的关联条件不要写错。 |
| **分组** | `GROUP BY`, `HAVING` | `WHERE` 在分组前过滤,`HAVING` 在分组后过滤。 |
| **去重** | `DISTINCT` | 注意 `COUNT(DISTINCT 列)` 的用法。 |
| **空值** | `IS NULL`, `IS NOT NULL` | 空值不能用 `= NULL` 判断,必须用 `IS NULL`。 |
| **排序** | `ORDER BY` | 默认升序(ASC),降序需写 `DESC`。 |
建议在面试前,使用本地数据库或在线SQL练习平台,将上述逻辑亲手敲一遍,特别是**窗口函数**和**复杂子查询**,这是目前区分候选人水平的关键。
