【问题标题】:How to remove rest of the ordered rows with the same ID after the first row which occurs more than once with that ID?如何在具有该 ID 多次出现的第一行之后删除具有相同 ID 的其余已排序行?
【发布时间】:2019-09-28 02:06:06
【问题描述】:

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 获取每一行(例如,这里的第一批是前 6 行)
  • Order 列排序
  • DataDataSpecifier 列视为一个比较单元(可以将它们视为一列,称为dataunit):
  • Order=1 开始保留尽可能多的行,直到dataunit 在批处理中出现多次为止
  • 保留最后一行,但删除具有相同 LinkID 和更大 Order 值的其余行

所以对于LinkID 120

  • Order 列对批次进行排序(此处已排序,但仍应这样做)
  • 从顶部开始查看(此处为Order=1),只要您没有看到批处理中出现超过 1 次的值即可
  • 在第一个重复的 Order=3 处停止(dataunit 1 10 也在 Order 5)。
  • 删除所有有LinkID=120 AND Order>=4

在对LinkID371(以及表中的所有其他LinkID)进行类似处理后,处理后的表将如下所示:

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 中执行此操作,使用一个可执行(和可重用)查询。

 


我在这里问了一个非常相似的问题:How to remove rest of the rows with the same ID starting from the first duplicate?

但由于我意识到问题中的原始过滤逻辑实际上并不是我所需要的,并且该问题已经得到正确回答,所以我不得不提出这个新问题。

【问题讨论】:

标签: sql sql-server tsql duplicates sql-delete


【解决方案1】:

在这里,我之前的解决方案已更新。几个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

【讨论】:

  • 非常感谢!这完美地工作并且非常容易修改以使用我的实际列和表名:)
猜你喜欢
  • 1970-01-01
  • 2019-09-26
  • 2011-05-01
  • 1970-01-01
  • 2023-03-16
  • 2015-11-30
  • 2022-08-20
  • 1970-01-01
  • 2021-11-14
相关资源
最近更新 更多