LeetCode第183题_从不订购的客户

LeetCode 第183题:从不订购的客户

题目描述

表: Customers

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
id 是该表的主键。
该表包含消费者的 id 和名字。

表: Orders

+-------------+------+
| Column Name | Type |
+-------------+------+
| id          | int  |
| customerId  | int  |
+-------------+------+
id 是该表的主键。
customerId 是 Customers 表中 id 的外键。
该表包含购买了产品的消费者的 id 。

编写一个 SQL 查询,报告从不订购任何东西的所有客户的名字。

返回结果表以任意顺序排列。

难度

简单

题目链接

点击在LeetCode中查看题目

示例

示例:

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

提示

  • Customers 表中的 id 是该表的主键。
  • Orders 表中的 id 是该表的主键。
  • Orders 表中的 customerId 是 Customers 表中 id 的外键。

解题思路

方法一:使用左连接(LEFT JOIN)和 IS NULL

解决这道题的关键是找出那些在 Customers 表中出现但在 Orders 表中没有订单的客户。这可以通过左连接和 IS NULL 条件来实现。

关键点:

  1. 使用 LEFT JOIN 将 Customers 表与 Orders 表连接
  2. 筛选出 Orders.customerId 为 NULL 的记录,这表示该客户没有订单
  3. 选择客户的名字作为结果输出

时间复杂度:O(n+m),其中 n 和 m 分别是 Customers 表和 Orders 表的行数
空间复杂度:O(n)

方法二:使用 NOT IN 子查询

另一种解决方法是使用 NOT IN 子查询,找出那些 id 不在 Orders 表的 customerId 列中的客户。

关键点:

  1. 使用子查询获取所有下过订单的客户 id
  2. 使用 NOT IN 筛选出不在这个集合中的客户
  3. 选择客户的名字作为结果输出

时间复杂度:O(n*m),其中 n 和 m 分别是 Customers 表和 Orders 表的行数
空间复杂度:O(m)

方法三:使用 NOT EXISTS 子查询

也可以使用 NOT EXISTS 子查询,检查是否存在与客户 ID 匹配的订单。

关键点:

  1. 使用相关子查询检查每个客户是否有订单
  2. 使用 NOT EXISTS 筛选出没有订单的客户
  3. 选择客户的名字作为结果输出

时间复杂度:O(n*m),其中 n 和 m 分别是 Customers 表和 Orders 表的行数
空间复杂度:O(1)

代码实现

SQL 实现(方法一:LEFT JOIN 和 IS NULL)

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

SQL 实现(方法二:NOT IN 子查询)

SELECT name AS Customers
FROM Customers
WHERE id NOT IN (SELECT customerIdFROM Orders
);

SQL 实现(方法三:NOT EXISTS 子查询)

SELECT name AS Customers
FROM Customers c
WHERE NOT EXISTS (SELECT 1FROM Orders oWHERE o.customerId = c.id
);

性能分析

各SQL实现的性能对比:

实现方法执行用时内存消耗特点
方法一389 ms0B使用LEFT JOIN,代码简洁清晰
方法二432 ms0B使用NOT IN,直观但性能较差
方法三394 ms0B使用NOT EXISTS,性能适中

补充说明

代码亮点

  1. 方法一使用 LEFT JOIN 和 IS NULL,是解决此类问题的标准方法
  2. 方法二和方法三使用子查询,思路直观
  3. 所有方法都考虑了正确的结果输出格式

方法比较

不同方法各有优缺点:

LEFT JOIN

  • 通常执行效率较高,特别是对于索引优化的表
  • 代码简洁,语义明确
  • 适用于需要显示额外信息的场景

NOT IN

  • 语法简单,易于理解
  • 在某些情况下性能可能较差,特别是当子查询结果较大时
  • 需要注意 NULL 值的处理

NOT EXISTS

  • 通常比 NOT IN 性能更好,尤其是对大型表
  • 不受 NULL 值影响
  • 在某些数据库中执行计划可能更优化

对于本题,LEFT JOIN 方法通常是更好的选择,因为它既清晰又高效。

常见错误

  1. 在方法一中,连接条件写错,导致匹配错误
  2. 在方法二中,没有处理 NULL 值的情况(虽然本题数据不包含 NULL)
  3. 筛选条件使用错误,如使用 o.id = NULL 而不是 o.id IS NULL
  4. 结果列名格式不符合要求

相关题目

  • 175. 组合两个表
  • 181. 超过经理收入的员工
  • 182. 查找重复的电子邮箱
  • 197. 上升的温度

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言的常用关键字

c语言的常用关键字 c语言的关键字表示数据类型的关键字autocharfloatdoubleintlongshortvoidsignedstruct、enum、unionunsigned 表示分支语句的关键字ifelseswitchbreakcasecontinuedefault 表示循环语句的关键字whiledoforgoto 用于修饰变量或函数的关键字constconst修饰变量…

MCU通用输入输出端口(GPIO)设计指南

在嵌入式系统开发中,MCU的GPIO接口是一个基础但非常实用的功能模块。GPIO全称是通用输入输出端口,它让MCU可以灵活地与外部设备进行交互。 GPIO的主要特点包括: 多功能性:每个引脚都可以单独配置为输入或输出 可编程性&#xff…

STM32完整内存地址空间分配详解

在STM32这类基于ARM Cortex-M的32位微控制器中,整个4GB的地址空间(从0x00000000到0xFFFFFFFF)有着非常系统化的分配方案,每个区域都有其特定的用途。下面我将详细介绍这些地址区域的分配及其功能: STM32完整内存地址空间分配详解(0x00000000…

实现水平垂直居中的多种方法

在前端开发中,元素的居中是一个常见但又经常让人头疼的问题。本文将全面总结各种CSS居中方法,特别是如何实现一个div的水平垂直居中。 为什么居中这么重要? 居中布局是现代网页设计中最基础也最重要的布局方式之一。无论是导航菜单、登录框…

如何实现服务的自动扩缩容(Auto Scaling)

在云计算和分布式系统的时代,系统的弹性和适应性已成为企业构建高效IT基础设施的核心需求。自动扩缩容(Auto Scaling)作为一种关键技术,旨在根据实时负载变化动态调整计算资源,以确保系统性能稳定,同时优化资源利用效率。简单来说,自动扩缩容是指系统能够根据预设规则或…

uniapp+vue3+ts 使用canvas实现安卓端、ios端及微信小程序端二维码生成及下载

加粗样式uniapp多端生成带二维码海报并保存至相册的实现 在微信小程序开发中,我们常常会遇到生成带有二维码的海报并保存到手机相册的需求,比如分享活动海报、产品宣传海报等。今天就来和大家分享一下如何通过代码实现这一功能。 准备工作 在开始之前&am…

架构师面试(三十八):注册中心架构模式

题目 在微服务系统中,当服务达到一定数量时,通常需要引入【注册中心】组件,以方便服务发现。 大家有没有思考过,注册中心存在的最根本的原因是什么呢?注册中心在企业中的最佳实践是怎样的?注册中心的服务…

Day.js和Moment.js对比,日期时间库怎么选?

在JavaScript的日期处理库中,Moment.js 和 Day.js 是两个非常流行的选择。本文将基于从npmtrends的数据,对这两个库进行详细的对比分析。 Moment.js的重度使用者。凡是遇到时间和日期的操作,就把Moment.js引用上。 直到有天我发现加载的mome…

罗默如何用木星卫星“宇宙钟表”测量光速?

一、17世纪的“宇宙级实验” 1676年,丹麦天文学家奥勒罗默(Ole Rmer)在巴黎天文台做出惊人发现: 木星卫星的“迟到早退”现象,竟能揭示光速的秘密! 通过观察木卫一(Io)的轨道周期变…

deepseek 技巧整理

1、导出word 和excel 功能,在使用以下提示词。 请帮我列出减肥期间可以吃的水果,并分析该水果含有的营养元素,以表格的形式星现。1.要以html的方式输出 2.要可以直接运行 3.页面要提供可以直接下载word和excel功能

思考软件框架

数据库是达梦数据库 假定里面有40张表,软件的业务逻辑比较复杂。 当然,依然是对数据库中数据的增,删,改,查,组合,显示。 但是也涉及到多种软件,多台设备之间的通信。 我们可以使用…

探索 Disruptor:高性能并发框架的奥秘

在当今的软件开发领域,处理高并发场景是一项极具挑战性的任务。传统的并发解决方案,如基于锁的队列,往往在高负载下表现出性能瓶颈。而 Disruptor 作为一个高性能的并发框架,凭借其独特的设计和先进的技术,在处理海量数…

前端面经-VUE3篇--vue3基础知识(一)插值表达式、ref、reactive

一、计算属性(computed) 计算属性(Computed Properties)是 Vue 中一种特殊的响应式数据,它能基于已有的响应式数据动态计算出新的数据。 计算属性有以下特性: 自动缓存:只有当它依赖的响应式数据发生变化时&#xff…

数据结构6 · BinaryTree二叉树模板

代码函数功能顺序如下: 1:destroy:递归删除树 2:copy:复制二叉树 3:preOrder:递归前序遍历 4:inOrder:递归中序遍历 5:postOrder:递归后续遍…

C++/SDL进阶游戏开发 —— 双人塔防游戏(代号:村庄保卫战 13)

🎁个人主页:工藤新一 🔍系列专栏:C面向对象(类和对象篇) 🌟心中的天空之城,终会照亮我前方的路 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录 十…

强化学习之基于无模型的算法之时序差分法

2、时序差分法(TD) 核心思想 TD 方法通过 引导值估计来学习最优策略。它利用当前的估计值和下一个时间步的信息来更新价值函数, 这种方法被称为“引导”(bootstrapping)。而不需要像蒙特卡罗方法那样等待一个完整的 episode 结束才进行更新&…

AE/PR模板 100个现代文字标题动态排版效果动画 Motion Titles

Motion Titles是一个令人惊艳的AE/PR模板,提供了100个现代文字标题的动态排版效果动画。这些动画效果能够为你的项目增添视觉冲击力和专业感,为文字标题注入活力和动感。该模板适用于Adobe After Effects CC或更高版本以及Adobe Premiere Pro 2020或更高…

【AI提示词】二八法则专家

提示说明 精通二八法则(帕累托法则)的广泛应用,擅长将其应用于商业、管理、个人发展等领域,深入理解其在不同场景中的具体表现和实际意义。 提示词 # Role: 二八法则专家## Profile - language: 中文 - description: 精通二八法…

前端八股 CSS 1

盒子模型 进行布局时将所有元素表示为一个个盒子box padding margin border content content:盒子内容 待显示的文本和图像 padding:内边距,内容和border之间的空间,不能为负数,受bkc影响 border:边框&#xff0c…

组件通信-$attrs

概述:$attrs用于实现当前组件的父组件,向当前组件的子组件通信(爷→孙)。 具体说明:$attrs是一个对象,包含所有父组件传入的标签属性。 注意:$attrs会自动排除props中声明的属性(可以认为声明过…