LeetCode题练习与总结:从不订购的客户--183

54 篇文章 0 订阅
10 篇文章 0 订阅

一、题目描述

SQL Schema > Pandas Schema 

Customers 表:

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
在 SQL 中,id 是该表的主键。
该表的每一行都表示客户的 ID 和名称。

Orders 表:

+-------------+------+
| Column Name | Type |
+-------------+------+
| id          | int  |
| customerId  | int  |
+-------------+------+
在 SQL 中,id 是该表的主键。
customerId 是 Customers 表中 ID 的外键( Pandas 中的连接键)。
该表的每一行都表示订单的 ID 和订购该订单的客户的 ID。

找出所有从不点任何东西的顾客。

以 任意顺序 返回结果表。

结果格式如下所示。

示例 1:

输入:
Customers table:
+----+-------+
| id | name  |
+----+-------+
| 1  | Joe   |
| 2  | Henry |
| 3  | Sam   |
| 4  | Max   |
+----+-------+
Orders table:
+----+------------+
| id | customerId |
+----+------------+
| 1  | 3          |
| 2  | 1          |
+----+------------+
输出:
+-----------+
| Customers |
+-----------+
| Henry     |
| Max       |
+-----------+

二、解题思路

  1. 首先,我们需要从 Customers 表中获取所有顾客的信息。
  2. 然后,我们需要从 Orders 表中找出所有已经下过订单的顾客的 ID。
  3. 接下来,我们要找出那些在 Orders 表中没有订单记录的顾客,即从未下过订单的顾客。
  4. 最后,我们将这些顾客的名称从 Customers 表中筛选出来。

三、具体代码

SELECT c.name AS Customers
FROM Customers c
LEFT JOIN Orders o ON c.id = o.customerId
WHERE o.customerId IS NULL;

解释:

  • 使用 LEFT JOIN 将 Customers 表和 Orders 表连接起来,基于顾客的 ID。
  • 在 WHERE 子句中,通过检查 o.customerId IS NULL 来找出那些在 Orders 表中没有匹配记录的顾客,即从未下过订单的顾客。
  • 最后,选择这些顾客的名称。

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

1. 时间复杂度
  • LEFT JOIN 操作:时间复杂度通常是 O(N * M),其中 N 是 Customers 表中的行数,M 是 Orders 表中的行数。这是因为在最坏的情况下,数据库可能需要遍历 Customers 表中的每一行,并为每一行检查 Orders 表中的所有行。
  • WHERE 子句:由于使用了 IS NULL 条件来筛选出未下订单的顾客,数据库在执行 LEFT JOIN 后,需要检查结果集中的每一行。这通常是一个 O(N) 操作,其中 N 是 LEFT JOIN 操作的结果集的大小。

综合来看,整个查询的时间复杂度是 O(N * M),其中 N 是 Customers 表的行数,M 是 Orders 表的行数。然而,如果 Orders 表中的 customerId 字段有索引,那么数据库可以更快地找到匹配的行,从而降低时间复杂度。

2. 空间复杂度
  • 结果集:空间复杂度取决于查询返回的结果集的大小。在最好情况下(没有顾客下订单),空间复杂度是 O(N),其中 N 是 Customers 表的行数。在最坏情况下(所有顾客都下订单),空间复杂度是 O(1),因为没有顾客会出现在结果集中。
  • JOIN 操作:在执行 LEFT JOIN 时,数据库可能需要存储中间结果集,其大小取决于 Customers 表和 Orders 表的行数。在最坏情况下,空间复杂度是 O(N * M),其中 N 是 Customers 表的行数,M 是 Orders 表的行数。

综上所述:

  • 时间复杂度:O(N * M),如果 customerId 有索引,则可能会降低。
  • 空间复杂度:最好情况下 O(N),最坏情况下 O(N * M)。

需要注意的是,这些分析是基于理论上的最坏情况,实际的性能会受到数据库的具体实现、索引、查询优化器等因素的影响。在实际情况中,数据库通常会采用各种优化技术来减少实际的查询时间和空间消耗。

五、总结知识点

  • 基础语法

    • SELECT:用于从数据库表中选取数据。
    • FROM:指定查询的数据来源表。
    • AS:为列或表指定别名,以便在查询结果中更易读或引用。
  • 表连接

    • LEFT JOIN:左连接是一种类型的 SQL 联接操作,它返回左表(Customers)的所有记录,即使在右表(Orders)中没有匹配的记录。如果右表中没有匹配,则结果集中的相关列将包含 NULL。
  • 条件过滤

    • WHERE:用于过滤查询结果中的行,只返回满足指定条件的行。
    • IS NULL:用于检查表达式的值是否为 NULL。
  • 列引用

    • c.name:使用表别名 c 来引用 Customers 表中的 name 列。
    • o.customerId:使用表别名 o 来引用 Orders 表中的 customerId 列。
  • 逻辑关系

    • ON:在 LEFT JOIN 中使用,指定连接条件,即如何匹配左表和右表中的行。
  • 外键关系

    • 虽然查询本身没有直接表达外键关系,但 LEFT JOIN 操作基于 Customers 表的 id 列和 Orders 表的 customerId 列之间的外键关系。
  • 子查询和连接的替代

    • 这个查询通过 LEFT JOIN 和 WHERE 子句代替了可能使用的子查询。子查询可能会在 WHERE 子句中以 NOT EXISTS 的形式出现,但在这里使用了更直接的 LEFT JOIN 方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一直学习永不止步

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

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

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

打赏作者

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

抵扣说明:

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

余额充值