當前位置: 妍妍網 > 資訊

SQL Server 中處理重復數據:保留最新記錄的兩種方案

2023-04-24資訊

大家在計畫開發過程中,資料庫幾乎是每一個後端開發者必備的技能,並且經常會遇到對於數據表重復數據的處理,一般需要去除重復保留最新的記錄。今天這裏給大家分享兩種種方案,希望對大家日常開發能夠提供一些幫助!

首先準備測試的數據表

建立一個包含ID, OrderDate, ProductName以及可選的SequenceID的商品購買記錄表Sales

CREATETABLE Sales
(
ID INTIDENTITY(1,1)PRIMARYKEY,
OrderDate DATENOTNULL,
ProductName VARCHAR(100)NOTNULL,
SequenceID INTIDENTITY(1,1)
);

-- 訂單日期增加當前日期預設值約束
ALTERTABLE Sales ADDDEFAULT(GETDATE())FOR OrderDate;

準備一些測試數據

INSERT INTO Sales (OrderDate, ProductName)
VALUES
('2023-04-01', '筆記本X1'), -- 範例商品A的最早購買日期
('2023-04-07', '智慧型手機Y7'),
('2023-04-15', '平板電腦Z3'),
('2023-04-09', '筆記本X1'), -- 商品A的第二次購買,較早日期
('2023-04-08', '智慧型手機Y7'), -- 商品B的第二次購買,較早日期
('2023-04-20', '平板電腦Z3'), -- 商品C的第二次購買,較晚日期
('2023-04-18', '筆記本X1'), -- 商品A的第三次購買,最新日期
('2023-04-22', '智慧型手機Y7 Pro'), -- 新產品,不同型號
('2023-04-25', '平板電腦Z3 Plus'), -- 新產品,不同型號
('2023-04-24 14:30:00', '筆記本X1'), -- 同日但較早時間的重復記錄
('2023-04-24 15:45:00', '筆記本X1'); -- 同日但較晚時間的記錄,應被視為最新

查詢效果如下:

方案一. 使用ROW_NUMBER()函式刪除重復項

ROW_NUMBER()函式是SQL Server中處理重復數據的強大工具之一,可以透過視窗函式來為每一組重復數據分配行號,然後保留每組數據中最新的一條記錄。

範例SQL語句

假設有一個表Sales,包含ID, OrderDate, ProductName等欄位,其中ID為主鍵,但ProductName和OrderDate上有重復數據,我們要保留每個產品的最新訂單記錄。

-- 查詢不是最新的重復記錄直接刪除
WITH CTE AS(
SELECT*,
ROW_NUMBER()OVER(PARTITIONBY ProductName ORDERBY OrderDate DESC)AS RowNum
FROM Sales
)
DELETEFROM CTE
WHERE RowNum >1;
-- 資料庫不操作直接查詢每一行不重復的最新記錄
WITH CTE AS(
SELECT*,
ROW_NUMBER()OVER(PARTITIONBY ProductName ORDERBY OrderDate DESC)AS RowNum
FROM Sales
)
select*FROM CTE
WHERE RowNum =1;

執行效果如下:

SQL說明

PARTITION BY ProductName :按照ProductName對數據分組。

ORDER BY OrderDate DESC :在每個分組內按OrderDate降序排序,確保最新記錄排在首位。

ROW_NUMBER() :為每組內的記錄分配一個行號,最新的記錄行號為1。

刪除重復記錄 :在CTE中刪除RowNum大於1的記錄,即除了每個分組最新的一條記錄外,其余視為重復並刪除。

直接查詢 :針對CTE篩選RowNum等於1的記錄

方案二. 使用臨時表的方式

第二種方法是使用臨時表來篩選並保留最新記錄。具體步驟如下:

建立臨時表 :首先,建立一個臨時表,結構與原表相同,用於儲存去重後的數據。

使用MERGE語句 :透過MERGE語句將原表數據與臨時表數據進行比較,保留每個唯一標識下的最新記錄。

INSERT INTO #TempSales
SELECT ID, OrderDate, ProductName
FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY ProductName ORDER BY OrderDate DESC) AS rn
FROM Sales
) t
WHERE t.rn = 1;
select * from #TempSales; -- 直接查詢就是去重後保留最新記錄的查詢數據
TRUNCATE TABLE Sales; -- 清空原表
-- 重新插入臨時表的數據給Sales。適用數據量不是特別大的情況
INSERT INTO Sales
SELECT * FROM #TempSales;
DROP TABLE #TempSales; -- 刪除臨時表

說明

該方案先透過臨時表儲存每個產品的最新記錄,然後清空原表,並將臨時表中的數據重新插入原表,最終達到保留最新記錄的目的。直接查詢臨時表就是所需要的數據。

小明工作助手新增pdf轉word、pdf轉圖片功能,歡迎免費體驗

歷史相關

優秀幹貨作者推薦

小編十多年工作經驗積累的電腦軟體分享給大家

CSDN:https://blog.csdn.net/xishining

個人部落格網站:https://programmerblog.xyz

往期推薦

!