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)
我现在需要找到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
Run Code Online (Sandbox Code Playgroud)
挑战在于考虑表中的行数,尽可能高效地完成此操作。
任何建议都非常感激。谢谢!
在原始表和派生表之间使用带有内部联接的更新语句应该非常快,只要您有适当的索引(您可以将更新语句复制到 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)