[英]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.