2013-02-20 67 views
0

我有一張表,用於存儲意外數據已被多次存儲的數據,因爲服務器端代碼上的用戶名字段的大小寫敏感性。用戶名字段應被視爲不區分大小寫。表格的重要欄目和數據可以在下面找到。在SQL Server中選擇基於兩列的行

我現在的要求是刪除除最近保存的數據外的所有數據。我正在爲此編寫一個sql腳本,並通過識別所有重複的行開始。該選擇返回如下表格。

對於每一行,如果存在最近一次保存,則爲LASTUPDATEDDATE,否則爲CREATEDDATE。在這個例子中,最近保存「用戶名」將是第3行

 
ID CREATEDDATE LASTUPDATEDDATE USERNAME       
-- ----------- --------------- -------- 
1 11-NOV-11     USERNAME         
2 01-NOV-11 02-NOV-11  username        
3 8-JAN-12     USERname  

我的腳本(選擇其中重複的用戶名會顯示所有行)看起來像:


SELECT 
    id, createddate, lastupdateddate, username 
FROM 
    table 
WHERE 
    LOWER(username) 
IN 
    (
    SELECT 
     LOWER(username) 
    FROM 
     table 
    GROUP BY 
     LOWER(username) 
    HAVING 
     COUNT(*) > 1 
) 
ORDER BY 
    LOWER(username) 

我現在的問題是:如何選擇行3以外的所有內容?我已經搜索了堆棧溢出與這個問題很好的匹配,但沒有發現足夠好的匹配。我知道我可能必須加入某種類型的聯盟,但是我不能真正理解它。真的很感謝你們正確的方向。

我們正在使用SQL Server,可能是一個相當新的版本。

回答

1

要刪除重複,你可以使用:

with todelete as (
    select t.*, 
      row_number() over (partition by lower(username) order by createddate desc) as seqnum 
    from table 
    ) 
delete from t 
where seqnum > 1 

這是一個順序號分配給每一行,從1開始爲最近。然後刪除最近的所有文件。

對於兩個日期,你可以使用:

with todelete as (
    select t.*, 
      row_number() over (partition by lower(username) order by thedate desc) as seqnum 
    from (select t.*, 
        (case when createddate >= coalesdce(updateddate, createddate) 
         then createddate 
         else updateddate 
        end) as thedate 
      from table 
     ) t 
    ) 
delete from t 
where seqnum > 1 
1

幾件事情要注意的 - 沒有任何理由在查詢中使用LOWER。 A = a在SQL Server中。

此外,要獲取正確的日期,您可以使用COALESCE來確定LastUpdatedDate是否存在,如果是,則按照它排序,否則按照CreatedDate排序。

把一起,這應該工作:

DELETE T 
FROM YourTable T 
    JOIN (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY username 
        ORDER BY COALESCE(lastupdateddate, createddate) DESC) as RN 
    FROM YourTable 
    ) T2 ON T.Id = T2.Id 
WHERE T2.RN > 1 

這裏是一個示例小提琴:http://www.sqlfiddle.com/#!3/51f7c/1

由於@Gordon正確的建議,你也可以使用一個CTE依賴於SQL Server的版本你使用(2005+):

WITH CTE AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY username 
           ORDER BY COALESCE(lastupdateddate, createddate) DESC) as RN 
    FROM YourTable 
    ) 
DELETE FROM CTE WHERE RN > 1