删除MariaDB中重复行的2种方法(忽略主键)

发布于

以下是当 MariaDB 中的表具有主键或唯一标识符列时从这些行中删除重复行的示例。

这些示例删除重复行,但保留一行。因此,在两行相同的情况下,它会删除其中一行并保留另一行。

示例数据

我们的示例使用以下数据:

SELECT * FROM Dogs;

结果:

+——-+———–+———-+ | DogId | FirstName | LastName | +——-+———–+———-+ | 1 | Bark | Smith | | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +——-+———–+———-+

我们可以看到前两行是重复的,最后三行也是重复的。

Thecolumn 保存唯一值(因为它是表的主键),因此,严格来说,没有重复项。但在实际情况下,您经常需要对包含主键的表进行重复数据消除。因此,在本文中,我们忽略主键,并在其余列中检测重复值。DogId

选项 1

让我们通过选择将删除的所有行来开始第一个选项:

SELECT * FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

结果:

+——-+———–+———-+ | DogId | FirstName | LastName | +——-+———–+———-+ | 2 | Bark | Smith | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +——-+———–+———-+

要删除这些重复的行,我们可以切换到:SELECT *``DELETE

DELETE FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

结果:

Query OK, 3 rows affected (0.017 sec)

为了验证结果,我们可以选择表中所有剩余的行:

SELECT * FROM Dogs;

结果:

+——-+———–+———-+ | DogId | FirstName | LastName | +——-+———–+———-+ | 1 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | +——-+———–+———-+

我们也可以使用函数而不是函数来更改删除哪些行。MAX()``MIN()

选项 2

在此示例中,我们假设表已还原到其原始状态(包含重复项)。

我们可以使用以下查询来检查重复的行:

SELECT * 
FROM Dogs d1, Dogs d2 
WHERE d1.FirstName = d2.FirstName 
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId 
AND d1.DogId = (
    SELECT MAX(DogId) 
    FROM Dogs d3 
    WHERE d3.FirstName = d1.FirstName 
    AND d3.LastName = d1.LastName
);

结果:

+——-+———–+———-+——-+———–+———-+ | DogId | FirstName | LastName | DogId | FirstName | LastName | +——-+———–+———-+——-+———–+———-+ | 2 | Bark | Smith | 1 | Bark | Smith | | 7 | Wag | Johnson | 5 | Wag | Johnson | | 7 | Wag | Johnson | 6 | Wag | Johnson | +——-+———–+———-+——-+———–+———-+

我们可以修改该查询以删除重复项:

DELETE FROM Dogs WHERE DogId IN (
    SELECT d2.DogId 
    FROM Dogs d1, Dogs d2 
    WHERE d1.FirstName = d2.FirstName 
    AND d1.LastName = d2.LastName 
    AND d1.DogId <> d2.DogId 
    AND d1.DogId=( 
        SELECT MIN(DogId) 
        FROM Dogs d3 
        WHERE d3.FirstName = d1.FirstName 
        AND d3.LastName = d1.LastName
    )
);

结果:

Query OK, 3 rows affected (0.075 sec)

该表现已消除重复数据。

我们可以通过再次选择所有行来验证这一点:

SELECT * FROM Dogs;

结果:

+——-+———–+———-+ | DogId | FirstName | LastName | +——-+———–+———-+ | 1 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | +——-+———–+———-+

如果愿意,我们可以使用而不是从重复项中删除其他行。MAX()``MIN()