如何在使用该 ID 多次出现的第一行之后删除具有相同 ID 的其余有序行?

How to remove rest of the ordered rows with the same ID after the first row which occurs more than once with that ID?

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

的行
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(以及 table 中的所有其他 LinkID)进行类似处理后,处理后的 table 将如下所示:

RowID   LinkID   Order  Data    DataSpecifier
1       120      1      1       1
2       120      2      1       3
3       120      3      1       10
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
.................................
.................................

我从来没有做过这么复杂的 SQL 查询。我知道查询必须是这样的:

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

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


我在这里问了一个非常相似的问题:

但是因为我意识到问题中我原来的过滤逻辑实际上并不是我需要的,而且那个问题已经被正确回答了,所以我不得不提出这个新问题。

在这里,我之前的解决方案更新了。几个 GROUP BY 应该足够了。代码很简单,一看就懂

设置:

IF OBJECT_ID('tempdb..#YourData') IS NOT NULL
    DROP TABLE #YourData

CREATE TABLE #YourData (
    RowID INT,
    LinkID INT,
    [Order] INT,
    Data INT,
    DataSpecifier INT)

INSERT INTO #YourData (
    RowID,
    LinkID,
    [Order],
    Data,
    DataSpecifier)
VALUES
    ('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')

解法:

;WITH DuplicatesByLinkID AS
(
    SELECT
        Y.LinkID,
        Y.Data,
        Y.DataSpecifier,
        [Order] = MIN([Order])
    FROM
        #YourData AS Y
    GROUP BY
        Y.LinkID,
        Y.Data,
        Y.DataSpecifier
    HAVING
        COUNT(*) > 1
),
FirstDuplicateByLinkID AS
(
    SELECT
        D.LinkID,
        MinOrder = MIN(D.[Order])
    FROM
        DuplicatesByLinkID AS D
    GROUP BY
        D.LinkID
)
DELETE Y FROM
    #YourData AS Y
    INNER JOIN FirstDuplicateByLinkID AS M ON
        Y.LinkID = M.LinkID AND
        Y.[Order] > M.MinOrder

SELECT * FROM #YourData

结果:

RowID   LinkID  Order   Data    DataSpecifier
1       120     1       1       1
2       120     2       1       3
3       120     3       1       10
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