> For the complete documentation index, see [llms.txt](https://houzidata.gitbook.io/sql/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://houzidata.gitbook.io/sql/di-3-zhang-duo-biao-cha-xun/tu-jie-mian-shi-ti-duo-biao-ru-he-cha-xun.md).

# 图解面试题：多表如何查询?

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUiBN7b-8VbkjLQdtP-%2F-MUiBdwU7QvgGk3lN0SF%2F%E5%A4%9A%E8%A1%A8%E5%A6%82%E4%BD%95%E6%9F%A5%E8%AF%A2_1.webp?alt=media\&token=1df79774-1367-4a61-bef0-0b56b9bda2ff)

**【题目】**

现在有两个表，“学生表” 记录了学生的基本信息，有 “学号”、“姓名”。

“成绩” 表记录了学生选修的课程，以及对应课程的成绩。

这两个表通过 “学号” 进行关联。

现在要查找出所有学生的学号，姓名，课程和成绩。

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUiBN7b-8VbkjLQdtP-%2F-MUiBi5pG0OlvF-foMZl%2F%E5%A4%9A%E8%A1%A8%E5%A6%82%E4%BD%95%E6%9F%A5%E8%AF%A2_2.jpg?alt=media\&token=fc6caa91-8967-4acf-bbd4-b822d8b8491c)

**【解题思路】**

**1. 确定查询结果**

题目要求查询所有学生的姓名，学号，课程和成绩信息

select 学号, 姓名, 课程, 成绩

查询结果的列名 “学号”、“姓名”，在“学生” 表里，列名 “课程”、“成绩” 在“成绩”表里，所以需要进行多表查询。

**2. 哪种联结呢？**

涉及到多表查询，在之前的课程《从零学会 sql：多表查询》里讲过需要用到联结。

多表的联结又分为以下几种类型：

1）左联结（left join），联结结果保留左表的全部数据

2）右联结（right join），联结结果保留右表的全部数据

3）内联结（inner join），取两表的公共数据

这个题目里要求 “所有学生”，而 “所有学生” 在“学生”表里。为什么不在 “成绩” 表里呢？

如果有的学生没有选修课程，那么他就不会出现在 “成绩” 表里，所以 “成绩” 表没有包含 “所有学生”。

所以要以 “学生” 表进行左联结，保留左边表（学生表）里的全部数据。

from 学生信息表 as a **left join** 成绩表 as b

**3. 两个表联结条件是什么？**

两个表都有 “学号”，所以联结条件为学号。

on a. 学号 = b. 学号

**4.最终 sql**

```sql
select a.学号,a.姓名,b.课程,b.成绩
from 学生 as a
left join 成绩 as b
on a.学号=b.学号;
```

运行结果：我们看到学号 4 都课程为空值，表示这名学生没有选修课程。

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUiBN7b-8VbkjLQdtP-%2F-MUiBlP5cS9TWN9qNJFb%2F%E5%A4%9A%E8%A1%A8%E5%A6%82%E4%BD%95%E6%9F%A5%E8%AF%A2_3.webp?alt=media\&token=df45a7ce-93ff-40ad-8ae3-1f27738f1c08)

**【本题考点】**

考察多表联结，以及如何选择联结的类型。记住课程里讲过的下面这张图，遇到多表联结的时候从这张图选择对于的 sql。

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUiBN7b-8VbkjLQdtP-%2F-MUiBpsDoUhVSaj45rOq%2F%E5%A4%9A%E8%A1%A8%E5%A6%82%E4%BD%95%E6%9F%A5%E8%AF%A2_4.webp?alt=media\&token=aa998fad-620f-46e6-b2b9-9041a9571197)

**【举一反三】**

有下面两个表

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUiBN7b-8VbkjLQdtP-%2F-MUiBsoIGWivFVsgArU5%2F%E5%A4%9A%E8%A1%A8%E5%A6%82%E4%BD%95%E6%9F%A5%E8%AF%A2_5.jpg?alt=media\&token=eb66e183-f45e-46d7-9be6-7b55153922e3)

编写一个 SQL 查询，满足条件：无论 person 是否有地址信息，都需要基于上述两表提供 person 的以下信息：

```sql
FirstName, LastName, City, State
```

**【思路】**

从表的结构可以看出，表 1（Person）是人的姓名信息，表 2（Address）是人的地址信息。

1）查询结果是两个表里的列名，所以需要多表查询

2）考虑到有的人可能没有地址信息，要是查询结构要查所有人，需要保留表 1（Person）里的全部数据，所以用左联结（left join）

3）两个表联结条件：两个表通过 PersonId 产生联结。

【参考答案】

```sql
select FirstName, LastName, City, State
from Person left join Address
on Person.PersonId = Address.PersonId
```

推荐：[如何提升你的分析技能，实现升职加薪？](http://mp.weixin.qq.com/s?__biz=MzAxMTMwNTMxMQ==\&mid=2649247566\&idx=2\&sn=5af748b677eb72028764dde0577675fb\&chksm=835fc77eb4284e68e8cfe3f08c5a671b9e080b2651f20b40b1c793ffda4042ae43ad8f35a755\&scene=21#wechat_redirect)

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUiBN7b-8VbkjLQdtP-%2F-MUiBwt6VPS3K7KJCMz7%2F%E5%A4%9A%E8%A1%A8%E5%A6%82%E4%BD%95%E6%9F%A5%E8%AF%A2_6.webp?alt=media\&token=9f9e1a41-b66d-440f-8ec4-a130be9ff765)
