在MariaDB中选择重复行的4种方法

发布于

如果您怀疑某个表在 MariaDB 数据库中有重复的行,则可以使用以下任何查询来了解有多少行是重复的。

示例数据

假设我们有一个包含以下数据的表:

SELECT * FROM Pets;

结果:

+———+———–+———–+ | PetId | PetName | PetType | |———+———–+———–| | 1 | Wag | Dog | | 1 | Wag | Dog | | 2 | Scratch | Cat | | 3 | Tweet | Bird | | 4 | Bark | Dog | | 4 | Bark | Dog | | 4 | Bark | Dog | +———+———–+———–+

前两行是重复的,后三行是重复的。

选项 1

我们可以使用以下查询来查看有多少行是重复的:

SELECT 
    DISTINCT PetId, 
    COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;

结果:

+———+———+ | PetId | Count | |———+———| | 1 | 2 | | 2 | 1 | | 3 | 1 | | 4 | 3 | +———+———+

如果需要,我们可以扩展列表以包含更多列:SELECT

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY PetId;

结果:

+———+———–+———–+———+ | PetId | PetName | PetType | Count | |———+———–+———–+———| | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 3 | +———+———–+———–+———+

我们也可以按计数降序排序,以便重复项最多的行首先出现:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY Count DESC;

结果:

+——-+———+———+——-+ | PetId | PetName | PetType | Count | +——-+———+———+——-+ | 4 | Bark | Dog | 3 | | 1 | Wag | Dog | 2 | | 3 | Tweet | Bird | 1 | | 2 | Scratch | Cat | 1 | +——-+———+———+——-+

选项 2

如果我们只想列出重复的行,我们可以使用 theclause 来排除非重复的行:HAVING

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
HAVING COUNT(*) > 1
ORDER BY PetId;

结果:

+——-+———+———+——-+ | PetId | PetName | PetType | Count | +——-+———+———+——-+ | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 3 | +——-+———+———+——-+

选项 3

另一种方法是将函数与子句一起使用,对结果集的输出进行编号。ROW_NUMBER()``PARTITION BY

SELECT 
    *, 
    ROW_NUMBER() OVER ( 
        PARTITION BY PetId, PetName, PetType 
        ORDER BY PetId, PetName, PetType
        ) AS Row_Number
FROM Pets;

Result:

+——-+———+———+————+ | PetId | PetName | PetType | Row_Number | +——-+———+———+————+ | 1 | Wag | Dog | 1 | | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 1 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +——-+———+———+————+

该子句将子句生成的结果集划分为应用该函数的分区。当我们为结果集指定分区时,每个分区都会导致重新开始编号(即每个分区中第一行的编号将从 1 开始)。PARTITION BY``FROM

选项 4

要从匹配的重复项中仅返回多余的行,我们可以将上面的查询用作公共表表达式,如下所示:

WITH cte AS 
    (
        SELECT 
            *, 
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
SELECT * FROM cte WHERE Row_Number <> 1;

结果:

+——-+———+———+————+ | PetId | PetName | PetType | Row_Number | +——-+———+———+————+ | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +——-+———+———+————+