2009-11-23 79 views
0

我正在查詢以選擇最大日期(一個datetime列)並保留其idrow_id。需要的是DELETE源表中的行。TSQL:根據最大日期刪除重複項(日期)

源數據

id  date   row_id(unique) 
1  11/11/2009 1 
1  12/11/2009 2 
1  13/11/2009 3 
2  1/11/2009  4 

預計倖存者

1  13/11/2009 3 
2  1/11/2009  4 

我需要什麼查詢來實現我期待的結果嗎?

+1

你說刪除重複項,但顯然你刪除了最小值和最大值之間的所有日期 - 你能澄清一下嗎? – Amarghosh 2009-11-23 12:52:11

回答

2

測試PostgreSQL的:

delete from table where (id, date) not in (select id, max(date) from table group by id); 
1

有這樣做的各種方式,但基本思路是一樣的:
- Indentify你想保持
行 - 在你的表進行比較,每一行你想保持
的那些 - 刪除任何不匹配

DELETE 
    [source] 
FROM 
    yourTable AS [source] 
LEFT JOIN 
    yourTable AS [keep] 
     ON [keep].id = [source].id 
     AND [keep].date = (SELECT MAX(date) FROM yourTable WHERE id = [keep].id) 
WHERE 
    [keep].id IS NULL 


DELETE 
    [yourTable] 
FROM 
    [yourTable] 
LEFT JOIN 
(
    SELECT id, MAX(date) AS date FROM yourTable GROUP BY id 
) 
    AS [keep] 
     ON [keep].id = [yourTable].id 
     AND [keep].date = [yourTable].date 
WHERE 
    [keep].id IS NULL 


DELETE 
    [source] 
FROM 
    yourTable AS [source] 
WHERE 
    [source].row_id != (SELECT TOP 1 row_id FROM yourTable WHERE id = [source].id ORDER BY date DESC) 


DELETE 
    [source] 
FROM 
    yourTable AS [source] 
WHERE 
    NOT EXISTS (SELECT id FROM yourTable GROUP BY id HAVING id = [source].id AND MAX(date) != [source].date) 
0

因爲你正在使用SQL Server 2000,而你卻被無法使用排過建立一個序列的技術並確定每個唯一ID的頂部行。

所以,你提出的技術是使用一個日期時間列來得到最高的1行來刪除重複。這可能會起作用,但有可能您仍可能獲得具有相同日期時間值的副本。但這很容易檢查。

首先檢查的假設,所有的行根據id和日期欄,獨特:

CREATE TABLE #TestTable (rowid INT IDENTITY(1,1), thisid INT, thisdate DATETIME) 
INSERT INTO #TestTable (thisid,thisdate) VALUES (1, '11/11/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (1, '12/11/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (1, '12/12/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (2, '1/11/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (2, '1/11/2009') 

SELECT COUNT(*) AS thiscount 
FROM #TestTable 
GROUP BY thisid, thisdate 
HAVING COUNT(*) > 1 

此示例返回的值是2 - 即使使用日期後,表明你仍然會結束與重複列以刪除重複項。如果你返回0,那麼你已經證明了你提出的技術是可行的。

在對生產數據進行去重處理時,我認爲應該採取一些預防措施並在測試前後進行測試。您應該創建一個表來保存您計劃刪除的行,以便在執行delete語句後您可以輕鬆恢復它們。

此外,最好事先知道您計劃刪除多少行,以便您可以驗證前後的計數 - 並且您可以評估刪除操作的大小。根據有多少行受到影響,您可以計劃何時運行該操作。

要在重複掃描過程之前進行測試,請查找事件。

-- Get occurrences of duplicates 
SELECT COUNT(*) AS thiscount 
FROM 
#TestTable 
GROUP BY thisid 
HAVING COUNT(*) > 1 
ORDER BY thisid 

這爲您提供具有相同ID的多行的行。將此查詢中的行捕獲到臨時表中,然後使用SUM運行查詢以根據您的密鑰獲取不唯一的行數。

要獲得您計劃刪除的行數,您需要根據您的唯一密鑰重複的行數以及基於唯一密鑰的不同行數。您從出現次數中減去不同的行。所有這些都很簡單 - 所以我會留給你的。

0

試試這個

declare @t table (id int, dt DATETIME,rowid INT IDENTITY(1,1)) 
INSERT INTO @t (id,dt) VALUES (1, '11/11/2009') 
INSERT INTO @t (id,dt) VALUES (1, '11/12/2009') 
INSERT INTO @t (id,dt) VALUES (1, '11/13/2009') 
INSERT INTO @t (id,dt) VALUES (2, '11/01/2009') 

查詢:

delete from @t where rowid not in(
select t.rowid from @t t 
inner join(
select MAX(dt)maxdate 
from @t 
group by id) X 
on t.dt = X.maxdate) 

select * from @t 

輸出:

id dt rowid 
1 2009-11-13 00:00:00.000 3 
2 2009-11-01 00:00:00.000 4 
0
delete from temp where row_id not in (
     select t.row_id from temp t 
     right join 
     (select id,MAX(dt) as dt from temp group by id) d 
     on t.dt = d.dt and t.id = d.id) 

我已經測試了這個答案..

0
INSERT INTO #t (id,dt) VALUES (1, '11/11/2009') 
INSERT INTO #t (id,dt) VALUES (1, '11/12/2009') 
INSERT INTO #t (id,dt) VALUES (1, '11/13/2009') 
INSERT INTO #t (id,dt) VALUES (2, '11/01/2009') 
select * from #t 

;WITH T AS(
select dense_rank() over(partition by id order by dt desc)NO,DT,ID,rowid from #t) 

DELETE T WHERE NO>1