需要删除一种项目类型的重复行,而不是其他类型的重复行

Posted

技术标签:

【中文标题】需要删除一种项目类型的重复行,而不是其他类型的重复行【英文标题】:Need to remove duplicate rows for one item type but not the others 【发布时间】:2013-11-25 20:55:35 【问题描述】:

我有一个这样的基本选择语句:

SELECT  
        ID, ProcedureCode, CONVERT(VARCHAR(8), StartTime, 112) AS 'DateOfService',
        SessionID'

 FROM dbo.TASK

结果是这样的:

 ID     ProcedureCode   DateOfService   SessionID
A164686     0034        20131014        9708
A164686     0034        20131021        9832
A164686     0002        20131007        9578
B463333     0002        20131003        9523
B463333     0002        20131009        9665
B463333     0002        20131016        9763

注意,对于 ID B463333,10 月份有三个 0002 程序。我想消除多余的两个,只留下最新的(基于 DateOfService)。

我知道我可以通过使用 row_number() 分区来完成此操作,但我不希望该逻辑应用于其他过程代码,例如 0034,我只想删除额外的 0002 过程代码(如果它们存在)。有重复的 0034 很好,但没有 0002。

有没有想过如何做到这一点?我认为能够做到这一点的唯一方法是使用 0002 过程代码制作一个临时表,并对上面的选择执行 UNION,但这似乎很混乱。

【问题讨论】:

【参考方案1】:

您可以将 ROW_NUMBER 之类的排名函数与 common-table-function 一起使用:

WITH CTE AS
(
     SELECT  ID, 
             ProcedureCode, 
             CONVERT(VARCHAR(8), StartTime, 112) AS 'DateOfService', 
             SessionID,
             RN = ROW_NUMBER() OVER (PARTITION BY ID, ProcedureCode 
                                     ORDER BY StartTime DESC)
     FROM dbo.TASK
     WHERE  ProcedureCode = '0002'
)
DELETE FROM CTE WHERE RN > 1

一个优点是您可以将其更改为轻松选择以查看您要删除的内容。

编辑:如果您实际上不想“消除”(删除)记录但从结果集中省略不需要的行,则可以使用此查询:

WITH CTE AS
(
     SELECT  ID, 
             ProcedureCode, 
             CONVERT(VARCHAR(8), StartTime, 112) AS 'DateOfService', 
             SessionID,
             RN = ROW_NUMBER() OVER (PARTITION BY ID, ProcedureCode 
                                     ORDER BY StartTime DESC)
     FROM dbo.TASK
)
SELECT ID, ProcedureCode, DateOfService, SessionID
FROM CTE
WHERE ProcedureCode <> '0002'
OR    RN = 1

【讨论】:

这是否也适用于非 0002 程序代码? @user2932397:它只会根据 ID、ProcedureCode 删除重复项。但是,我必须承认,我只阅读了第一段,而不是以 “我知道我可以通过使用 row_number()” 开头的部分。 编辑:我已经编辑了我的答案。您可以简单地将Where 添加到CTEDELETE 语句中。 我不明白这个解决方案将如何工作,因为 ProcedureCode = '0002' 有一个 WHERE 子句,这意味着我将排除 0034 和其他几个过程代码。 @Baub:这是你的话:“但我不希望该逻辑适用于其他程序代码,例如 0034,我只想删除额外的 0002 程序代码,如果它们存在。重复的 0034 很好,但不是 0002。” 这意味着您只想删除重复的 0002 行(正如 @user2932397 也提到的那样)。我是不是误会了? 是的,我只想删除 0002 的重复行,但 0034(和其他)的重复行是可以接受的。如果我运行您的 select 语句,我将永远不会有 0034 的过程代码,但我需要包含这些。

以上是关于需要删除一种项目类型的重复行,而不是其他类型的重复行的主要内容,如果未能解决你的问题,请参考以下文章

是否可以创建一个函数而不是两个具有相同目的但参数类型不同的函数? (我可以删除重复的代码吗?)[重复]

如何删除唯一行并保持重复? SQL

按钮类型=使用php isset而不是输入类型按钮提交[重复]

为啥java的一些概念需要使用包装类而不是原始数据类型[重复]

使用嵌套行(类型 STRUCT)对表 SQL 进行重复数据删除

使用 JCL 排序删除特定记录类型的重复项