由于服务器端代码上的用户名字段具有案例敏感性,因此我有一个存储数据的表,其中多次存储了意外数据。用户名字段应视为不区分大小写。表格的重要列和数据可以在下面找到。
我现在的要求是删除除最近保存的数据以外的所有数据。我正在为此编写一个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,可能是一个非常新的版本。
答案 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