T-SQL基于列删除重复项

T-SQL基于列删除重复项,sql,sql-server,tsql,Sql,Sql Server,Tsql,屏幕截图显示了表格的前8行。对于相同的id(每个id有数千行),基于相同的“updatetime”,我只想保留第一行,删除其余的行。例如,在这里,我想删除第3、5、8行。两行的所有列可以完全相同(这里,当updatetime相同时,UpdateMillisec不同,但不是必需的)。屏幕截图是查询的结果,我现在没有主键(屏幕截图中最左边的列现在在表中不可用)。我应该写什么SQL代码?提前谢谢 给出一个按列划分的行号,并按时间列排序,然后删除不需要的行 查询 ;with cte as( se

屏幕截图显示了表格的前8行。对于相同的id(每个id有数千行),基于相同的“updatetime”,我只想保留第一行,删除其余的行。例如,在这里,我想删除第3、5、8行。两行的所有列可以完全相同(这里,当updatetime相同时,UpdateMillisec不同,但不是必需的)。屏幕截图是查询的结果,我现在没有主键(屏幕截图中最左边的列现在在表中不可用)。我应该写什么SQL代码?提前谢谢


给出一个按列划分的行号,并按
时间
列排序,然后删除不需要的行

查询

;with cte as(
    select [rn] = row_number() over(
        partition by [id], [lastprice], [updatetime] 
        order by [id], [updatetime], [updateMillisec]
    ), *
    from [your_table_nam]
)
select * from cte -- first select and check whether these are the rows that has to be deleted
where [rn] > 1;
如果确定,则删除
[rn]
大于
1
的行

delete from cte
where [rn] > 1;

有一种简单的方法可以删除重复的行

在第一步中,我们将对记录进行排序并添加行号。
第二步是删除rownumber>1的行

WITH CTE AS
(
SELECT  *
       ,ROW_NUMBER() OVER 
                (PARTITION BY id, updatetime
                     ORDER BY id, updatetime, UpdateMillisec ASC
                     ) AS RowNum
  FROM yourtable

)
SELECT * FROM CTE                    -- for checking the result before deleting
-- DELETE FROM CTE WHERE RowNum > 1  -- uncomment this row for the final DELETE
注意:
要确定哪一条是第一条记录,哪一条是后续(第二条、第三条,…)记录,我们必须对数据进行排序
在删除它们之前,请务必先用
SELECT*FROM CTE
检查结果集

在您的案例中,我检查了上述查询的结果集,即:

id  lastprice   updatetime          UpdateMillisec  RowNum
211709  51370   09:30:00.0000000    500             1
211709  51380   09:30:01.0000000    0               1
211709  51370   09:30:01.0000000    500             2
211709  51370   09:30:02.0000000    0               1
211709  51370   09:30:02.0000000    500             2
211709  51370   09:30:03.0000000    0               1
211709  51370   09:30:04.0000000    0               1
211709  51370   09:30:04.0000000    500             2

正如我们所看到的,正是那些您想要删除的记录的RowNum=2。因此,最后我们可以将
选择*
更改为
删除
,然后再次执行查询。

我喜欢@Estban p.的解决方案。我很想进一步尝试。事实证明,这样做也是可能的:

DELETE seq FROM (SELECT ROW_NUMBER() 
       OVER(PARTITION BY id, updatetime ORDER BY id, updatetime, updatems ASC) AS RowNum
FROM tbl ) seq where rownum>1;

因此,您甚至不必使用CTE,请参阅此处的演示

检查此处如果您没有主键和“UpdateMillisec不同,但不是必需的”,那么您将很难识别要删除的记录。每次应用
delete
子句时,您仍然可以使用类似于
top()
的方法将删除操作限制在有限数量的记录上。一个合适的主键会很有帮助。谢谢大家,所有答案都很好!谢谢你的解决方案。不知道可以直接从CTE中删除记录!不客气。不久前,我在stackoverflow上找到了这个方便的解决方案,每次我需要删除重复项时都会使用它:)谢谢大家,所有答案都很好!