Article / 文章
LeetCode 第175题:组合两个表
表: Person +-------------+---------+ | 列名 | 类型 | +-------------+---------+ | PersonId | int | | FirstName | varchar | | LastName | varchar | +-------------+---------+ PersonId 是该表的主
题目描述
表: Person
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| PersonId | int |
| FirstName | varchar |
| LastName | varchar |
+-------------+---------+
PersonId 是该表的主键
表: Address
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| AddressId | int |
| PersonId | int |
| City | varchar |
| State | varchar |
+-------------+---------+
AddressId 是该表的主键
编写一个SQL查询来报告 Person 表中每个人的姓、名、城市和州。如果 PersonId 的地址不在 Address 表中,则报告为空 null 。
难度
简单
题目链接
示例
示例1:
Person表:
+----------+----------+-----------+
| PersonId | LastName | FirstName |
+----------+----------+-----------+
| 1 | Wang | Allen |
| 2 | Alice | Bob |
+----------+----------+-----------+
Address表:
+-----------+----------+---------------+------------+
| AddressId | PersonId | City | State |
+-----------+----------+---------------+------------+
| 1 | 2 | New York City | New York |
| 2 | 3 | Leetcode | California |
+-----------+----------+---------------+------------+
输出:
+-----------+----------+---------------+----------+
| FirstName | LastName | City | State |
+-----------+----------+---------------+----------+
| Allen | Wang | Null | Null |
| Bob | Alice | New York City | New York |
+-----------+----------+---------------+----------+
解释:
地址表中没有 PersonId = 1 的地址,所以它们的城市和州返回 null。
AddressId = 1 包含了 PersonId = 2 的地址信息。
提示
- 语句的执行环境为SQL Server
解题思路
方法:LEFT JOIN
这道题要求我们查询 Person 表中每个人的姓、名、城市和州,如果某个人在 Address 表中没有对应的地址,则城市和州应该报告为 null。
解题的关键在于使用 LEFT JOIN(左连接)操作,它能确保 Person 表中的每一条记录都会出现在结果集中,即使这个人在 Address 表中没有对应的地址信息。
步骤:
- 以 Person 表作为左表,Address 表作为右表
- 使用 PersonId 作为连接条件进行 LEFT JOIN
- 选择需要的列:FirstName, LastName, City 和 State
SQL中的主要连接类型及其区别:
- INNER JOIN(内连接):仅返回两表中匹配的行
- LEFT JOIN(左连接):返回左表中的所有行,右表没有匹配的行则用 NULL 值填充
- RIGHT JOIN(右连接):返回右表中的所有行,左表没有匹配的行则用 NULL 值填充
- FULL JOIN(全连接):返回两表中的所有行,任何不匹配的行则用 NULL 值填充
时间复杂度:O(n+m),其中 n 和 m 分别是 Person 表和 Address 表的行数 空间复杂度:O(n),需要存储结果集
代码实现
SQL 实现
SELECT P.FirstName, P.LastName, A.City, A.State
FROM Person P
LEFT JOIN Address A
ON P.PersonId = A.PersonId;
性能分析
SQL 查询的性能分析:
| 特点 | 说明 |
|---|---|
| 执行用时 | 392 ms |
| 内存消耗 | 0B |
| 特点 | 简单直观的 LEFT JOIN 操作 |
补充说明
代码亮点
- 使用 LEFT JOIN 确保 Person 表中的所有人都会被查询出来
- 清晰的列名前缀(P. 和 A.)提高了查询的可读性
- 简洁明了的实现,没有复杂的条件判断
常见错误
- 使用 INNER JOIN 而不是 LEFT JOIN,导致没有地址信息的人被过滤掉
- 忘记指定表别名,在复杂查询中可能导致列引用不明确
- JOIN 条件使用错误的列,导致连接结果不正确