【问题标题】:Removing same entries in MySQL table删除 MySQL 表中的相同条目
【发布时间】:2021-04-07 17:30:31
【问题描述】:

我是 MySQL 的初学者。这里我刚刚创建了一个表

CREATE TABLE Student (
    Rollno int,
    LastName varchar(255),
    FirstName varchar(255),
    Gpa float,
);

创建表后,我在以下查询的帮助下添加了值

USE persons;
INSERT INTO student
VALUES
 (1, 'Aa', 'A', 8.5),
 (2, 'Bb', 'B', 8.6),
 (3, 'Cc', 'C', 8.7),
 (4, 'Dd', 'D', 8.4);

我刚刚运行了两次上述查询,结果有两个条目,如下所示

所以我只是想删除重复的条目,结果数据库应该类似于

尽管我搜索并尝试过,但我没有任何独特的价值,例如 answer 中提到的 id

我在this answer 的帮助下再次尝试,代码如下所示

WITH cte AS (
    SELECT
        Rollno,
        LastName,
        FirstName,
        Gpa,
        ROW_NUMBER() OVER (
            PARTITION BY
                Rollno
            ORDER BY
                Rollno
        )RN
     FROM
        persons.student
)
DELETE FROM cte
WHERE RN > 1;

但上面会抛出错误说明

错误代码:1288。 DELETE的目标表cte不可更新

所以我只想要一个最佳解决方案,在表中包含单个条目。

【问题讨论】:

标签: mysql sql


【解决方案1】:

这是我使用您的数据测试的解决方案。感谢您提供完整且易于测试的案例!

mysql> alter table student add column id int auto_increment primary key first;
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> select * from student;
+----+--------+----------+-----------+------+
| id | Rollno | LastName | FirstName | Gpa  |
+----+--------+----------+-----------+------+
|  1 |      1 | Aa       | A         |  8.5 |
|  2 |      2 | Bb       | B         |  8.6 |
|  3 |      3 | Cc       | C         |  8.7 |
|  4 |      4 | Dd       | D         |  8.4 |
|  5 |      1 | Aa       | A         |  8.5 |
|  6 |      2 | Bb       | B         |  8.6 |
|  7 |      3 | Cc       | C         |  8.7 |
|  8 |      4 | Dd       | D         |  8.4 |
+----+--------+----------+-----------+------+
8 rows in set (0.00 sec)

mysql> delete s1 from student as s1 join student as s2 on s1.rollno=s2.rollno and s1.id > s2.id;
Query OK, 4 rows affected (0.03 sec)

mysql> select * from student;
+----+--------+----------+-----------+------+
| id | Rollno | LastName | FirstName | Gpa  |
+----+--------+----------+-----------+------+
|  1 |      1 | Aa       | A         |  8.5 |
|  2 |      2 | Bb       | B         |  8.6 |
|  3 |      3 | Cc       | C         |  8.7 |
|  4 |      4 | Dd       | D         |  8.4 |
+----+--------+----------+-----------+------+
4 rows in set (0.00 sec)

你的评论:

此查询中的s1s2 通常称为“表别名”,但您应该将它们视为 别名。它们一次引用一行,因此您可以比较各行中的值。

假设有这样两行:

+----+--------+----------+-----------+------+
| id | Rollno | LastName | FirstName | Gpa  |
+----+--------+----------+-----------+------+
|  1 |      1 | Aa       | A         |  8.5 |
|  5 |      1 | Aa       | A         |  8.5 |

哪一行可以用s1表示,哪一行可以用s2这样连接条件成立?

两行的 Rollno 相同,所以连接条件 s1.rollno=s2.rollno 都满足。

一行的id 的值小于另一行,因此要满足连接条件s1.id > s2.id,我们知道s2 是id 为1 的第一行,s1 是id 为 5 的第二行。

因此,连接条件的两项共同保证s1s2 将引用具有相同Rollno 的两行,而s2 将具有较小的id 值。

+----+--------+----------+-----------+------+
| id | Rollno | LastName | FirstName | Gpa  |
+----+--------+----------+-----------+------+
|  1 |      1 | Aa       | A         |  8.5 | <-- s2
|  5 |      1 | Aa       | A         |  8.5 | <-- s1

我们希望保留具有较小 id 值 (s2) 的“第一”行,并删除另一行 (s1)。因此delete s1 from ...。在 MySQL 的多表删除语法中,您指定将在 from 关键字之前删除哪一行。 from 子句中定义的其他行别名 (s2) 不会被删除。

【讨论】:

  • 我能否更准确地了解s1.id &gt; s2.id 的工作原理。
猜你喜欢
  • 1970-01-01
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 2012-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多