我有一个像这样的基本选择语句:
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,但这看起来很混乱。
答案 0 :(得分: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