LeetCode题练习与总结:组合两个表--175

51 篇文章 0 订阅
10 篇文章 0 订阅

一、题目描述

SQL Schema > Pandas Schema > 

表: Person

+-------------+---------+
| 列名         | 类型     |
+-------------+---------+
| PersonId    | int     |
| FirstName   | varchar |
| LastName    | varchar |
+-------------+---------+
personId 是该表的主键(具有唯一值的列)。
该表包含一些人的 ID 和他们的姓和名的信息。

表: Address

+-------------+---------+
| 列名         | 类型    |
+-------------+---------+
| AddressId   | int     |
| PersonId    | int     |
| City        | varchar |
| State       | varchar |
+-------------+---------+
addressId 是该表的主键(具有唯一值的列)。
该表的每一行都包含一个 ID = PersonId 的人的城市和州的信息。

编写解决方案,报告 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 的地址信息。

二、解题思路

  1. 首先需要连接Person表和Address表,以便可以从Address表中获取每个人的城市和州信息。
  2. 由于题目要求即使某些人的地址信息在Address表中不存在,也需要在结果中显示这些人的信息,因此需要使用左连接(LEFT JOIN)。
  3. 在左连接时,以Person表为主表,Address表为从表,并使用PersonId作为连接条件。
  4. 最后,选择需要的列:FirstName、LastName、City和State。

三、具体代码

SELECT 
    p.FirstName, 
    p.LastName, 
    a.City, 
    a.State
FROM 
    Person p
LEFT JOIN 
    Address a 
ON 
    p.PersonId = a.PersonId;

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 表的扫描(Scan):在最坏的情况下,如果没有索引,数据库可能需要对Person表进行全表扫描来找到所有的记录。时间复杂度为O(n),其中n是Person表中的行数。

  • 连接操作(Join):对于Person表中的每一行,数据库需要查找Address表中对应的行。如果没有索引,这也可能是一个全表扫描,时间复杂度为O(m),其中m是Address表中的行数。由于是左连接,每个Person表中的行都会与Address表进行匹配尝试,因此总体时间复杂度为O(n*m)。

  • 如果PersonId上有索引,则查找Address表中对应行的操作将降低到O(log m)的时间复杂度,因为可以使用二分查找。因此,总体时间复杂度将降低到O(n*log m)。

  • 因此,如果没有索引,时间复杂度为O(nm);如果PersonId上有索引,时间复杂度为O(nlog m)。

2. 空间复杂度
  • 结果集(Result Set):空间复杂度取决于查询返回的结果集大小。在最坏的情况下,如果Person表中的每行都有一个对应的Address表中的行,那么结果集的大小将是n(Person表的行数)。因此,空间复杂度为O(n)。

  • 缓存和临时数据结构:数据库在执行查询时可能会使用缓存和临时数据结构来存储中间结果。在最坏的情况下,这可能会需要额外的空间,其大小取决于查询优化器的实现和查询计划。然而,这通常不会超过O(n + m)。

  • 因此,空间复杂度为O(n),因为结果集的大小与Person表的行数成正比。

请注意,这些分析是基于理论上的假设,实际的时间复杂度和空间复杂度可能会因数据库的实际操作和优化而有所不同。

五、总结知识点

1. SQL查询结构

  • SELECT:用于指定查询返回的列。
  • FROM:用于指定查询操作的表。
  • LEFT JOIN:用于指定左连接操作,将左侧表(Person)的记录与右侧表(Address)的记录进行匹配。

2. 表别名p 和 a:为表PersonAddress分别定义了别名,这样可以简化查询语句,尤其是在涉及到多表连接时。

3. 列引用p.FirstNamep.LastName:使用点符号(.)来引用Person表(别名p)中的列。

  • a.Citya.State:同样使用点符号来引用Address表(别名a)中的列。

4. 连接条件ON p.PersonId = a.PersonId:定义了左连接的条件,即Person表中的PersonId列必须与Address表中的PersonId列相等。

5. 左连接(LEFT JOIN):确保即使Address表中没有匹配的PersonIdPerson表中的记录也会出现在结果集中,并且对于Address表中缺失的匹配项,相关列将显示为NULL

6. 笛卡尔积:虽然在此查询中不是显式的,但LEFT JOIN隐含了笛卡尔积的概念,即左侧表中的每一行都与右侧表中的每一行进行组合,然后根据连接条件进行筛选。

7. SQL执行顺序:尽管查询语句是按照SELECTFROMLEFT JOIN的顺序编写的,但实际的执行顺序是FROM -> LEFT JOIN -> SELECT。即先确定要操作的表和连接方式,然后确定需要返回的列。

8. NULL值处理:在左连接中,理解NULL值的使用,即当右侧表中没有匹配的行时,相关列的值将为NULL

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直学习永不止步

谢谢您的鼓励,我会再接再厉的!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值