首页 > 解决方案 > 如何从第一个重复项开始删除具有相同 ID 的其余行?

问题描述

我的表有以下结构DataTable:每一列都是 int 数据类型,RowID是一个标识列和主键。LinkID是一个外键,链接到另一个表的行。

RowID   LinkID   Order  Data    DataSpecifier
1       120      1      1       1
2       120      2      1       3
3       120      3      1       10
4       120      4      1       13
5       120      5      1       10
6       120      6      1       13
7       371      1      6       2
8       371      2      3       5
9       371      3      8       1
10      371      4      10      1
11      371      5      7       2
12      371      6      3       3
13      371      7      7       2
14      371      8      17      4
.................................
.................................

我正在尝试执行一个查询,该查询LinkID以下列方式更改每个批次:

所以对于LinkID 120

LinkID 371在对(以及表中的每个其他人)进行类似处理之后LinkID,处理后的表将如下所示:

RowID   LinkID   Order  Data    DataSpecifier
1       120      1      1       1
2       120      2      1       3
3       120      3      1       10
4       120      4      1       13
7       371      1      6       2
8       371      2      3       5
9       371      3      8       1
10      371      4      10      1
11      371      5      7       2
12      371      6      3       3
.................................
.................................

我已经完成了很多 SQL 查询,但从来没有这么复杂的事情。我知道我需要使用类似这样的查询:

DELETE FROM DataTable  
WHERE RowID IN (SELECT RowID
                FROM DataTable
                WHERE -- ?
                GROUP BY LinkID
                HAVING COUNT(*) > 1 -- ?
                ORDER BY [Order]);

但我似乎无法解决这个问题并正确查询。我最好在纯 SQL 中使用一个可执行(和可重用)查询来执行此操作。

标签: sqlsql-servertsqlduplicatessql-delete

解决方案


我们可以在这里尝试使用 CTE 以使事情变得更容易:

WITH cte AS (
    SELECT *,
        COUNT(*) OVER (PARTITION BY LinkID, Data, DataSpecifier ORDER BY [Order]) - 1 cnt
    FROM DataTable
),
cte2 AS (
    SELECT *,
        SUM(cnt) OVER (PARTITION BY LinkID ORDER BY [Order]) num
    FROM cte
)

DELETE
FROM cte
WHERE num > 0;

在此处输入图像描述

这里的逻辑是COUNT用作分析函数来识别重复记录。我们使用LinkIDwithData和的分区DataSpecifier。然后将任何Order值大于或等于第一个非零计数记录的记录作为删除目标。

这是一个演示,表明 CTE 的逻辑是正确的:

演示


推荐阅读