力扣刷MySQL-第三弹(详细讲解)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 力扣刷MySQL-第三弹(详细讲解)

🚀删除重复电子邮箱

表: Person

+-------------+---------+

| Column Name | Type    |

+-------------+---------+

| id          | int     |

| email       | varchar |

+-------------+---------+

id 是该表的主键列(具有唯一值的列)。

该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。

编写解决方案 删除 所有重复的电子邮件,只保留一个具有最小 id 的唯一电子邮件。

(对于 SQL 用户,请注意你应该编写一个 DELETE 语句而不是 SELECT 语句。)

运行脚本后,显示的答案是 Person 表。驱动程序将首先编译并运行您的代码片段,然后再显示 Person 表。Person 表的最终顺序 无关紧要 。

返回结果格式如下示例所示。

示例 1:

输入:

Person 表:

+----+------------------+

| id | email            |

+----+------------------+

| 1  | john@example.com |

| 2  | bob@example.com  |

| 3  | john@example.com |

+----+------------------+

输出:

+----+------------------+

| id | email            |

+----+------------------+

| 1  | john@example.com |

| 2  | bob@example.com  |

+----+------------------+

解释: john@example.com重复两次。我们保留最小的Id = 1。

解法一:

1.分组

2.首先,题目也提示删除我们要用delete,而不是select

3.众所周知,delect不能删除某个字段的值,这点很重要,温习一下

4.要求是保留每个唯一电子邮件地址对应的最小 id。自然地,我们可以考虑使用 group by 方法来实现这一点。

5.Person.group by('email') 将根据 email 列中的唯一值对 Person 进行分组。我们根据 email 列中的唯一值将 Person 分成多个组。

6.这种分组允许我们将具有相同 email 的行分组在一起,以便我们可以分别对每个组进行操作。

7.那么我们接下来实现一下

8.select * from person group by email (给邮件分组)

9.那么分组之后的情况就是,组1是john@example.com和john@example.com,组2是bob@example.com

10.那么我们再查找每个组唯一的电子邮件的最小id,用到了聚合函数

11.select min(id) from person group by email

12.然后我们要去选择最小的id的值也就是min(id),我们最好给它起一个别名,但最好不要是id,如果是id,因为我们等一下要在它外面还要套一个select去查询这个id,所有很容易与表中的id弄混,我们这里给它起名为id1

13.之后我们在外面套一个select,去查询这个最小i

14.select id1 from (SELECT MIN(id) AS id1 FROM Person GROUP BY email)

15.除此之外我们就想到了用not in,不在这个id1只能的数,我们给它删了,很明显每个组最小的id就是一个是1,一个是2,那么3不是1和2,那么我们就删了,用where

16.SELECT id1 FROM (SELECT MIN(id) AS id1 FROM Person GROUP BY email)

17.DELETE FROM Person WHERE id NOT IN (SELECT id1 FROM (SELECT MIN(id) AS id1 FROM Person GROUP BY email)AS temp);

18.很多人看不懂为什么外面好像多套了一个select,不能没有这个嘛?

19.不能写成

DELETE FROM Person
WHERE id NOT IN (
    SELECT MIN(id) AS id1
    FROM Person
    GROUP BY email
);

20.不行,这样会报错,因为删除和查询不能同时作用在一张表,如果您在查询中使用了与删除操作相同的表,可能会导致不可预测的结果。这是因为,在 MySQL 中,删除操作会立即从表中删除符合条件的行。因此,如果您在查询中使用了一个已经被删除的行,那么查询结果就会不正确。

21.此时我们就可以用套一个子查询的办法,包装一下避免这个错误,同时也要取上别名

22.即下面的代码,AS temp其实也就是一个伪装

DELETE FROM Person
WHERE id NOT IN (
  SELECT id1 FROM (
    SELECT MIN(id) AS id1
    FROM Person
    GROUP BY email
  ) AS temp
);

方法二:

自连接,且使用 DELETE 和 WHERE 子句
实现

通过将此表与自身在 Email 列上连接,我们可以得到以下代码。

SELECT p1.*
FROM Person p1,
    Person p2
WHERE
    p1.Email = p2.Email ;

然后,我们需要找到具有相同电子邮件地址的其他记录中较大的 id。因此,我们可以在 WHERE 子句中添加一个新条件,如下所示。

SELECT p1.*
FROM Person p1,
    Person p2
WHERE
    p1.Email = p2.Email AND p1.Id > p2.Id ;

因为我们已经得到了要删除的记录,所以我们可以将这个语句改为 DELETE。

DELETE p1 FROM Person p1,
    Person p2
WHERE
    p1.Email = p2.Email AND p1.Id > p2.Id

🚀上升的温度

表: Weather


+---------------+---------+

| Column Name   | Type    |

+---------------+---------+

| id            | int     |

| recordDate    | date    |

| temperature   | int     |

+---------------+---------+

id 是该表具有唯一值的列。

该表包含特定日期的温度信息

编写解决方案,找出与之前(昨天的)日期相比温度更高的所有日期的 id

返回结果 无顺序要求 。

结果格式如下例子所示。

示例 1:

输入:

Weather 表:

+----+------------+-------------+

| id | recordDate | Temperature |

+----+------------+-------------+

| 1  | 2015-01-01 | 10          |

| 2  | 2015-01-02 | 25          |

| 3  | 2015-01-03 | 20          |

| 4  | 2015-01-04 | 30          |

+----+------------+-------------+

输出:

+----+

| id |

+----+

| 2  |

| 4  |

+----+

解释:

2015-01-02 的温度比前一天高(10 -> 25)

2015-01-04 的温度比前一天高(20 -> 30)

解题思路:

首先,我们需要找到每一天与前一天的温度比较情况。这可以通过自连接(self-join)来实现,即将 Weather 表与自身连接,以便比较相邻日期的温度情况。

1.自连接表: 首先,我们对 Weather 表进行自连接,以便能够比较相邻日期的温度情况。我们将使用 w1 和 w2 作为表的别名,分别代表连接中的两个不同实例。

SELECT w1.id AS w1_id, w1.recordDate AS w1_date, w1.temperature AS w1_temp,
       w2.id AS w2_id, w2.recordDate AS w2_date, w2.temperature AS w2_temp
FROM Weather w1
JOIN Weather w2 ON DATEDIFF(w2.recordDate, w1.recordDate) = 1;

这将返回一个结果集,其中包含了相邻日期的温度信息。

2.筛选条件: 我们需要进一步筛选出温度更高的日期。

WHERE w2.temperature > w1.temperature

这个条件将确保只有当后一天的温度高于前一天时才会被选择。

3.最终结果: 最后,我们只需选择符合条件的日期的 id。

SELECT w2.id
FROM Weather w1
JOIN Weather w2 ON DATEDIFF(w2.recordDate, w1.recordDate) = 1
WHERE w2.temperature > w1.temperature

这将给出所有温度比前一天更高的日期的 id。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
SQL ice
力扣刷MySQL-第八弹(详细讲解)
力扣刷MySQL-第八弹(详细讲解)
|
4月前
​​力扣刷MySQL-第九弹(详细讲解)
​​力扣刷MySQL-第九弹(详细讲解)
|
4月前
|
SQL 关系型数据库 MySQL
力扣刷MySQL-第七弹(详细讲解)
力扣刷MySQL-第七弹(详细讲解)
|
4月前
|
SQL 关系型数据库 MySQL
力扣刷MySQL-第六弹(详细讲解)
力扣刷MySQL-第六弹(详细讲解)
|
4月前
|
SQL 测试技术
力扣刷MySQL-第五弹(详细讲解)
力扣刷MySQL-第五弹(详细讲解)
|
4月前
|
SQL
力扣刷MySQL-第四弹(详细讲解)
力扣刷MySQL-第四弹(详细讲解)
|
4月前
|
SQL Python
力扣刷MySQL-第二弹(详细解析)
力扣刷MySQL-第二弹(详细解析)
|
4月前
|
开发框架 关系型数据库 MySQL
力扣刷MySQL-第一弹(详细解析)
力扣刷MySQL-第一弹(详细解析)
|
7天前
|
关系型数据库 MySQL Linux
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
|
8天前
|
SQL 关系型数据库 MySQL
【MySQL-5】DDL的数据库操作:查询&创建&删除&使用(可cv代码+演示图)
【MySQL-5】DDL的数据库操作:查询&创建&删除&使用(可cv代码+演示图)