🚀删除重复电子邮箱
表: 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。