表 evaeve 中按 E_RecordID 分組,每組保留最大 id (最新記錄),刪除其餘重復行。
DECLARE
@id1 INT, @oldid INT,
@e_RecordID INT, @Old_e_RecordID INT;
DECLARE price CURSOR FOR
SELECT id, E_RecordID FROM evaeve ORDER BY E_RecordID DESC;
OPEN price;
FETCH NEXT FROM price INTO @oldid, @Old_e_RecordID;
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM price INTO @id1, @e_RecordID;
IF @Old_e_RecordID = @e_RecordID
BEGIN
-- 同組非最大 id,刪除
DELETE FROM evaeve WHERE id = @id1;
END
SET @oldid = @id1;
SET @Old_e_RecordID = @e_RecordID;
END
CLOSE price;
DEALLOCATE price;
DELETE FROM evaeve
WHERE id NOT IN (
SELECT MAX(id) FROM evaeve GROUP BY E_RecordID
);
| 維度 | 游標循環 | 集合 SQL (NOT IN) | 集合 SQL (NOT EXISTS) | ROW_NUMBER() (2005+) |
|---|---|---|---|---|
| 性能 | 極差 (RBAR) | 良好 | 優秀 | 優秀 |
| NULL 安全 | N/A | 不安全 (子查詢含 NULL 則全不匹配) | 安全 | 安全 |
| 可讀性 | 低 | 高 | 高 | 高 |
| 適用版本 | 所有 | 所有 | 所有 | 2005+ |
| 保留邏輯靈活性 | 高 (可編寫複雜判斷) | 低 (僅聚合函數) | 中 (相關子查詢) | 高 (任意排序/分區) |
DELETE FROM evaeve e1
WHERE EXISTS (
SELECT 1 FROM evaeve e2
WHERE e2.E_RecordID = e1.E_RecordID
AND e2.id > e1.id
);
邏輯:存在同組且 id 更大的行 → 刪除當前行。等價於保留每組最大 id。
;WITH CTE AS (
SELECT id,
ROW_NUMBER() OVER (PARTITION BY E_RecordID ORDER BY id DESC) AS rn
FROM evaeve
)
DELETE FROM CTE WHERE rn > 1;
ORDER BY id DESC 保留最大,ASC 保留最小,CreateTime DESC 保留最新。PARTITION BY Col1, Col2。DECLARE @BatchSize INT = 5000, @RowCount INT = 1;
WHILE @RowCount > 0
BEGIN
DELETE TOP (@BatchSize) FROM evaeve
WHERE id NOT IN (
SELECT MAX(id) FROM evaeve GROUP BY E_RecordID
);
SET @RowCount = @@ROWCOUNT;
-- 可選:WAITFOR DELAY '00:00:01' 降低鎖競爭
END
-- 業務鍵唯一,防止重復入庫
ALTER TABLE evaeve ADD CONSTRAINT UQ_evaeve_RecordID UNIQUE (E_RecordID);
-- 或允許歷史但標識最新
ALTER TABLE evaeve ADD IsLatest BIT DEFAULT 1;
CREATE UNIQUE INDEX UX_evaeve_Latest ON evaeve (E_RecordID) WHERE IsLatest = 1; -- 過濾索引 (2008+)