我有一个名为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
我现在需要找到OriginId
和MetricId
相等的重复项,除了第一项匹配以外的所有匹配项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
考虑到表格中的行数,挑战是尽可能高效地完成这项工作。
任何建议都非常感谢。谢谢!
答案 0 :(得分:4)
使用带有原始表和派生表之间的内部联接的更新语句应该非常快,只要你有适当的索引(你可以将更新语句复制到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)
以下是更新声明:
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
测试结果:
SELECT *
FROM tblLog
清理
DROP table tblLog