繁体   English   中英

根据SQL Server中的两列选择行

[英]Select rows based on two columns in 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,可能是一个非常新的版本。

要删除重复项,您可以使用:

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

有几点需要注意 - 没有理由在查询中使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM