根据SQL Server中的两列选择行

时间:2013-02-20 15:27:11

标签: sql sql-server

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

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

对于每一行,最近的保存是LASTUPDATEDDATE(如果存在),否则为CREATEDDATE。对于此示例,“username”的最新保存将是第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行以外的所有内容?我搜索了Stack Overflow以获得与此问题的完美匹配,但发现没有足够好的匹配。我知道我可能要加入某种形式,但不能真正理解它。非常感谢能够朝着正确的方向前进。

我们使用的是SQL Server,可能是一个非常新的版本。

2 个答案:

答案 0 :(得分: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 :(得分:1)

有几点需要注意 - 没有理由在查询中使用LOWER。在SQL Server中A = a。

另外,要获取正确的日期,可以使用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