如果ID /名称重复,请选择单个记录

时间:2012-11-07 21:13:53

标签: tsql select duplicates

这似乎是一个非常简单的问题,但我现在似乎无法弄明白......

以下是我从当前存储过程中获取的数据的简化视图:

ID     Name         Class     Desc
---    -----        ------    -----
84     Calvin J.    2B
53     Fred D.      3B
53     Fred D.      ADJ       Change/Correction
47     Mary F.      3A
47     Mary F.      ADJ       New Product
09     Donald M.    ADJ       Cancelled
21     Richard G.   ADJ       Bad Debt
21     Richard G.   ADJ       Cancelled

我需要修改我的程序,以便每个人只选择一条记录。如果一个人有调整,我只想选择带调整的记录而忽略另一个记录。基于以上所述,这是我试图返回的结果集:

ID     Name         Class     Desc
---    -----        ------    -----
84     Calvin J.    2B
53     Fred D.      ADJ       Change/Correction
47     Mary F.      ADJ       New Product
09     Donald M.    ADJ       Cancelled
21     Richard G.   ADJ       Cancelled

请帮忙!

更新

我刚刚意识到这个查询还有一个额外的要求;如果有两个调整,其中一个有“坏债”的描述而另一个有“已取消”,则需要选择带有“已取消”描述的记录(参见上面的更新数据)。

1 个答案:

答案 0 :(得分:0)

这应该可以解决问题:

SELECT ID, Name, Class, [Desc]
FROM (
  SELECT ID, Name, Class, [Desc],
         ROW_NUMBER() OVER(PARTITION BY ID
                           ORDER BY CASE WHEN Class = 'ADJ'
                                         THEN 0 ELSE 1 END) rn
  FROM Table1
) A
WHERE rn = 1

它看起来比实际上更可怕。内部查询包含使用ROW_NUMBER()计算的额外列。这样做会对您的行进行编号,对于每个不同的ID(在PARTITION BY中指定),从1开始。 ORDER BY告诉ROW_NUMBER()如何对行进行排序,这是一个案例陈述,说Class = 'ADJ'行应该在所有其他行之前。然后在最后我们只抓取编号为1的行。如果有ID的行,则结果选择ADJ行,否则选择常规行。

根据更新的要求进行编辑
如果您有其他优先级标准,则可以将其添加到ORDER BY,就像在常规查询中ORDER BY一样。通常,仅执行内部查询而不过滤到rn = 1是有帮助的,这样您就可以准确地看到行号的分配方式。

以下是应满足新要求的更新查询:

SELECT ID, Name, Class, [Desc]
FROM (
  SELECT ID, Name, Class, [Desc],
         ROW_NUMBER() OVER(PARTITION BY ID
                           ORDER BY
                             CASE WHEN Class = 'ADJ'
                                  THEN 0 ELSE 1 END,
                             CASE WHEN [Desc] = 'Cancelled'
                                  THEN 0 ELSE 1 END) rn
  FROM Table1
) A
WHERE rn = 1

See it in action here.