查找重复项并使用第一个找到的重复项的 ID 标记重复项

And*_*sen 0 t-sql sql-server sql-update

我有一个名为 的表log,其中有数百万行。目前,它看起来像这样:

Id       OriginId MetricId  Value  IsDuplicate DuplicateId
-------- -------- --------- ------ ----------- -----------
1        50ECC7F6 FC7A477F  2.00   0           0
3        50ECC7F6 FC7A477F  2.00   0           0
4        8800B985 7F438F09  5.00   0           0
5        50ECC7F6 FC7A477F  2.00   0           0
Run Code Online (Sandbox Code Playgroud)

我现在需要找到OriginIdMetricId相等的重复项,将除第一个匹配项之外的所有匹配项设置IsDuplicate为 1,并DuplicateId设置为Id第一个出现的行的 。

预期的结果是这样的:

Id       OriginId MetricId  Value  IsDuplicate DuplicateId
-------- -------- --------- ------ ----------- -----------
1        50ECC7F6 FC7A477F  2.00   0           0
3        50ECC7F6 FC7A477F  0.00   1           1
4        8800B985 7F438F09  5.00   0           0
5        50ECC7F6 FC7A477F  0.00   1           1
Run Code Online (Sandbox Code Playgroud)

挑战在于考虑表中的行数,尽可能高效地完成此操作。

任何建议都非常感激。谢谢!

ATC*_*ATC 5

在原始表和派生表之间使用带有内部联接的更新语句应该非常快,只要您有适当的索引(您可以将更新语句复制到 SSMS,然后单击 ctrl+L,这将显示估计的值)执行计划。如果需要索引,您将在结果窗格的顶部看到它)。

创建并填充示例表:

CREATE TABLE tblLog
(
    Id int identity(1,1),
    OriginId varchar(10),
    MetricId varchar(10), 
    Value numeric(10,2),
    IsDuplicate bit null default 0,
    DuplicateId int null default 0
)

INSERT INTO tblLog (OriginId, MetricId, Value) VALUES
('50ECC7F6', 'FC7A477F', 2.00),
('50ECC7F6', 'FC7A477F', 2.00),
('8800B985', '7F438F09', 5.00),
('50ECC7F6', 'FC7A477F', 2.00)
Run Code Online (Sandbox Code Playgroud)

以下是更新声明:

UPDATE tblLog
SET IsDuplicate = 1,
    DuplicateId = dupId
FROM tblLog INNER JOIN
(
    SELECT MIN(Id) as dupId, OriginId as oid, MetricId as mid
    FROM tblLog
    GROUP BY OriginId, MetricId
) orig
ON OriginId = oid and MetricId = mid and id > dupId
Run Code Online (Sandbox Code Playgroud)

检测结果:

SELECT *
FROM tblLog 
Run Code Online (Sandbox Code Playgroud)

清理

DROP table tblLog
Run Code Online (Sandbox Code Playgroud)