Duplication

重複的行序列

  • October 21, 2019

我有一個歷史表 (EnrollmentHistory) 用於跟踪對我的數據庫中另一個表 (Enrollment) 的更改。EnrollmentHistory 表由一個觸發器填充,該觸發器在對 Enrollment 表進行更改時觸發。觸發器將行更改的行複製到 EnrollmentHistory 表中,然後對歷史表中的行進行更改。註冊歷史表僅跟踪註冊更改的某些屬性(例如,保留對成績的更改,但不保留對筆記的更改)。觸發器最初設計不正確的方式,它擷取了對行的任何更新,包括沒有任何更改或未跟踪的屬性之一發生更改的更新。觸發器已被修復,但歷史表中存在大量重複資訊。

我正在嘗試清理並清理這張桌子,但是我不確定我能做到這一點的最佳方法。由於這是一個歷史表,我想清理按時間順序出現的重複項。這是一個例子,

LOG_ID   ENROLLMENT_ID   GRADE     CREATE_DATE        CHANGE_DATE     
-------- --------------- ------- ------------------ ------------------ 
     1               1           1/1/2015 10:00AM   1/1/2015 11:00AM  
     2               1   A       1/1/2015 11:00AM   1/1/2015 11:02AM  
     3               1   A       1/1/2015 11:02AM   1/1/2015 11:05AM  
     4               1   B+      1/1/2015 11:05AM   1/1/2015 11:07AM  
     5               1   A       1/1/2015 11:07AM   1/1/2015 11:09AM  
     6               1   B+      1/1/2015 11:09AM                     

LOG_ID 2 和 3 是重複的,因為兩者之間沒有任何變化,所以我想刪除 Log ID 3。另一方面,日誌 4 和 6 不是重複的,因為兩者之間發生了變化(即等級從 B+ 變化-> A -> B+)。是否可以編寫一個查詢來按照我想要的方式清理和清理這個表?我只需要執行一次,所以它不一定需要高效。

$$ should work, make sure you have a backup ;) $$ 我添加了第二個註冊 ID,還有一個重複的…

Declare @Test TABLE (
LOG_ID  INT PRIMARY KEY,
ENROLLMENT_ID INT,
GRADE CHAR(2),
CREATE_DATE DATETIME,   
CHANGE_DATE DATETIME)

INSERT INTO @Test VALUES

(1,1,'' ,'1/1/2015 10:00AM','1/1/2015 11:00AM'),
(2,1,'A'    ,'1/1/2015 11:00AM','1/1/2015 11:02AM'),
(3,1,'A'    ,'1/1/2015 11:02AM','1/1/2015 11:05AM'),
(4,1,'B+','1/1/2015 11:05AM','1/1/2015 11:07AM'),
(5,1,'A'    ,'1/1/2015 11:07AM','1/1/2015 11:09AM'),
(6,1,'B+','1/1/2015 11:09AM','1/1/2015 11:09AM'),
(7,2,'B+','1/1/2015 11:05AM','1/1/2015 11:07AM'),
(8,2,'A'    ,'1/1/2015 11:07AM','1/1/2015 11:09AM'),
(9,2,'B+','1/1/2015 11:09AM','1/1/2015 11:09AM'),
(10,2,'B+','1/1/2015 11:09AM','1/1/2015 11:09AM'),
(11,2,'B+','1/1/2015 11:09AM','1/1/2015 11:09AM')

; WITH CTE AS (
SELECT LOG_ID, ENROLLMENT_ID, Grade, ROW_NUMBER() OVER (ORDER BY LOG_ID) TH
FROM @Test T
)

--SELECT DATA.*
--FROM @Test Data
--JOIN (
--SELECT
--  A.Log_ID
--FROM CTE A
--JOIN CTE B
--ON A.ENROLLMENT_ID = B.ENROLLMENT_ID
--AND A.GRADE = B.GRADE
--AND A.TH = B.TH + 1 ) DUPLICATED_DATA
--ON DATA.LOG_ID = DUPLICATED_DATA.LOG_ID

DELETE Data
FROM @Test Data
JOIN (
SELECT
   A.Log_ID
FROM CTE A
JOIN CTE B
ON A.ENROLLMENT_ID = B.ENROLLMENT_ID
AND A.GRADE = B.GRADE
AND A.TH = B.TH + 1 ) DUPLICATED_DATA
ON DATA.LOG_ID = DUPLICATED_DATA.LOG_ID

SELECT * FROM @Test

好吧,如果我們假設您使用的是 MS SQL Server,則此查詢將查找並刪除重複的行,而保留原始行。您可能希望首先針對範例表或在測試環境中執行它,並確認結果是您想要的。此外,您可以註釋 DELETE 行並執行註釋的 SELECT,以了解查詢實際刪除了多少行。

DELETE EnrollmentHistory  
--SELECT COUNT(*)   
FROM EnrollmentHistory
LEFT OUTER JOIN (
  SELECT MIN(RowId) AS RowId, ENROLLMENT_ID, GRADE, CREATE_DATE, CHANGE_DATE   --columns to define unique row
  FROM EnrollmentHistory
  GROUP BY ENROLLMENT_ID, GRADE, CREATE_DATE, CHANGE_DATE                      --columns to define unique row
) AS KeepRows ON
  EnrollmentHistory.RowId = KeepRows.RowId
WHERE
  KeepRows.RowId IS NULL

引用自:https://dba.stackexchange.com/questions/97236