0

我有一个存储数据的表,由于服务器端代码上的用户名字段区分大小写,因此意外存储了多次数据。用户名字段应被视为不区分大小写。该表的重要列和数据可以在下面找到。

我现在的要求是删除除最近保存的数据之外的所有数据。我正在为此编写一个 sql 脚本,并从识别所有重复的行开始。此选择返回如下表。

对于每一行,最近的保存是 LASTUPDATEDDATE(如果存在),否则是 CREATEDDATE。对于此示例,“用户名”的最新保存将是第 3 行。

ID CREATEDDATE LASTUPDATEDDATE USERNAME                           
-- ----------- ---------------- --------
1 11-11-11 用户名                                
2 01-NOV-11 02-NOV-11 用户名                            
3 2012 年 1 月 8 日用户名      

我的脚本(选择出现重复用户名的所有行)如下所示:


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 行之外的所有内容?我在 Stack Overflow 上搜索了该问题的匹配项,但没有找到足够匹配的匹配项。我知道我可能必须加入某种形式,但我无法真正理解它。非常感谢您朝着正确的方向前进。

我们正在使用 SQL Server,可能是一个相当新的版本。

4

2 回答 2

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
于 2013-02-20T15:30:06.387 回答
1

有几点需要注意——没有理由LOWER在您的查询中使用。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 正确建议的那样,您还可以根据您使用的 SQL Server 版本(2005+)使用 CTE:

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
于 2013-02-20T15:45:42.020 回答