T-SQL技術收集——刪除重複資料
在工作和麵試中,經常出現如何查詢或者刪除重複資料的問題,如果有主鍵,那還好辦一點,如果沒有主鍵,那就有點麻煩。
當一個表上沒有輔助鍵時,如果使用SSMS介面來刪除,就會報錯(注意,本人測試環境是2012,所以介面可能會有所不一樣,但是對結果沒有任何影響):
因為在建立表後插入資料是沒有做判斷。但是在刪除時,為了保證資料庫的一致性,RDBMS還是會做判斷從而拒絕執行這類操作。
說明:
要解決這種問題,除了在設計的過程中做好之外,還可以在資料沒有重複資料的情況下,使用ALTER TABLE ADD Constraint語句來增加約束。
但是要刪除現有的重複值,使用SSMS介面是無法實現的,就算能實現,當資料量到達一定程度,也是不現實的。此時只能使用T-SQL語句,搭配SET ROWCOUNT 1讓資料的處理方式一次一行或這使用DELETE TOP (1)的方式刪除,注意,括號是必須的。
SET ROWCOUNT { number | @number_var }:使 SQL Server 在返回指定的行數之後停止處理查詢。如果需要取消限制,只需要使用SETROWCOUNT 0就可以。
下面是例子:
--使用set rowcount 3設定,查詢所有資料
SET ROWCOUNT 3
SELECT * FROM AdventureWorks.HumanResources.Department
--結果僅返回3行
結果如下:
--使用set rowcount 3,修改所有資料
UPDATE AdventureWorks.HumanResources.Department
SET name=name
(3 行受影響)
--回覆原有設定
SET ROWCOUNT 0
最後使用TOP (N)設定搭配INSERT/UPDATE /DELETE ,注意這部分只適合2005以後。
--使用TOP(3)設定,查詢所有資料,注意是要有括號的
SELECT TOP(3) * FROM AdventureWorks.HumanResources.Department
--結果返回3行
UPDATE TOP(3) AdventureWorks.HumanResources.Department SET name =name
(3 行受影響)
另外,SQLServer提供了一個系統函式@@ROWCOUNT來返回影響行數。以下是例子:
--使用@@rowcount系統函式返回影響行數
SELECT EmployeeID,Title
FROM AdventureWorks.HumanResources.Employee
WHERE Title LIKE '%Manager%'
GO
SELECT @@ROWCOUNT 'Result'
解決方法:
首先建立一個測試表和插入測試資料:
USE tempdb
GO
CREATE TABLE MyT
(
[SID] INT,
sname VARCHAR(10),
sdt DATETIME
)
GO
--插入測試資料
INSERT INTO MyT VALUES (1,'Lu','2012/01/01');
INSERT INTO MyT VALUES (1,'Lu','2012/07/08');
INSERT INTO MyT VALUES (1,'Lu','2012/04/03');
INSERT INTO MyT VALUES (2,'Tian','2012/03/01');
INSERT INTO MyT VALUES (2,'Tian','2012/05/09');
INSERT INTO MyT VALUES (2,'Tian','2012/01/01');
INSERT INTO MyT VALUES (3,'AD','2012/01/08');
INSERT INTO MyT VALUES (3,'AD','2012/03/01');
INSERT INTO MyT VALUES (4,'Sun','2012/02/01');
INSERT INTO MyT VALUES (1,'Lu','2012/01/01');
INSERT INTO MyT VALUES (1,'Lu','2012/07/08');
INSERT INTO MyT VALUES (1,'Lu','2012/04/03');
INSERT INTO MyT VALUES (2,'Tian','2012/03/01');
INSERT INTO MyT VALUES (2,'Tian','2012/05/09');
INSERT INTO MyT VALUES (2,'Tian','2012/01/01');
INSERT INTO MyT VALUES (3,'AD','2012/01/08');
INSERT INTO MyT VALUES (3,'AD','2012/03/01');
INSERT INTO MyT VALUES (4,'Sun','2012/02/01');
GO
第一種方法:
使用SET ROWCOUNT 1方法來刪除重複資料:
需要搭配WHILE 1=1無限迴圈,搭配BREAK作為終止。針對找出來的重複資料,使用GROUP BY 和HAVING COUNT(1)>1作為篩選條件,可以避免所有資料被刪除。
SET ROWCOUNT 1
WHILE 1=1
BEGIN
DELETE FROM MyT
WHERE [sid] IN
(
SELECT [sid] FROM MyT
GROUP BY [sid],sname
HAVING COUNT(1)>1
)
IF @@ROWCOUNT=0
BREAK
END
SET ROWCOUNT 0
--可以發現,重複的資料已經刪除
SELECT * FROM MyT
第二種方法:
使用DELETE TOP(N)方法,先把剛才插入測試資料的指令碼再執行,可以多執行幾次。DELETE TOP(1)可以用來替代SET ROWCOUNT 1:
WHILE 1=1
BEGIN
DELETE TOP(1) FROM MyT
WHERE [sid] IN
(
SELECT [sid] FROM MyT
GROUP BY [sid],sname
HAVING COUNT(1)>1
)
IF @@ROWCOUNT=0
BREAK
END
結果和上面的一樣。
擴充:保留最近的一行資料:
有時候不僅僅要去掉重複資料,也要保證剩下的是最新的資料(日期最大),此時可以藉助索引,使用索引排序,然後把日期最小的那些刪掉,只保留日期最大的那一筆。
--建立複合索引,利用索引將資料以編號和日期升序排序
CREATE INDEX IDX_DT ON MyT([sid],sdt ASC)
GO
--修改刪除語句,搭配with index查詢提示
WHILE 1=1
BEGIN
DELETE TOP(1) FROM MyT
WHERE [sid] IN
(
SELECT [sid] FROM MyT WITH (INDEX(idx_dt))
GROUP BY [sid],sname
HAVING COUNT(1) >1
)
IF @@ROWCOUNT=0
BREAK
END
查詢結果:
SELECT * FROM MyT
注意:
為了向後相容,括號在 SELECT 語句中是可選的。
我們建議您始終對 SELECT 語句中的 TOP 使用括號,這樣,就可以與在 INSERT、UPDATE、MERGE 和 DELETE 語句中需要使用括號保持一致(在這種情況下括號是必需的)。
(出自SQL SERVER 2012聯機叢書)
相關文章
- 刪除重複資料
- mongodb刪除重複資料MongoDB
- sqlserver中刪除重複資料SQLServer
- PostgreSQL刪除表中重複資料SQL
- 解析postgresql 刪除重複資料案例SQL
- MS SQL Server 刪除重複行資料SQLServer
- mysql 刪除表中重複的資料MySql
- excel刪除重複資料保留一條 如何刪掉重複資料只留一條Excel
- Oracle中刪除表中的重複資料Oracle
- ORACLE批量刪除無主鍵重複資料Oracle
- 事件溯源投影模式:重複資料刪除策略 - domaincentric事件模式AI
- 使用Java Stream API中DistinctBy刪除重複資料JavaAPI
- 刪除oracle重複值Oracle
- mysql 刪除重複項MySql
- JavaScript 刪除重複字元JavaScript字元
- 【常用方法推薦】如何刪除MySQL的重複資料?MySql
- oracle刪除重資料方法Oracle
- JavaScript 刪除字串重複字元JavaScript字串字元
- VSCode刪除重複的空行VSCode
- 刪除重複id的記錄
- JavaScript 刪除陣列重複元素JavaScript陣列
- Remove Duplicate Letters 刪除重複元素REM
- JavaScript陣列刪除重複元素JavaScript陣列
- JavaScript刪除字串中重複字元JavaScript字串字元
- JavaScript陣列刪除重複內容JavaScript陣列
- MySQL資料庫中刪除重複記錄的方法總結[推薦]MySql資料庫
- 刪除排序陣列中的重複項排序陣列
- MariaDB刪除重複記錄效能測試
- 刪除有序陣列中的重複項 II陣列
- C# 批次刪除Excel中的重複行C#Excel
- 刪除字串中的所有相鄰重複項字串
- sql刪除重複記錄只保留一條SQL
- ES6刪除字串中重複的元素字串
- “刪庫跑路”重現江湖,技術和制度如何保障資料安全?
- 刪除資料
- whk我【資料刪除】你個【資料刪除】的
- 查詢/刪除重複的資料(單個欄位和多個欄位條件)
- c#刪除有序陣列中的重複項C#陣列
- 0026-刪除有序陣列中的重複項陣列