1

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

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

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

请帮忙!

更新

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

4

1 回答 1

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()。这样做是对您的行进行编号,从 1 开始为每个不同的ID(在 中指定PARTITION BY)。ORDER BY告诉ROW_NUMBER()如何对行进行排序,是一个 case 语句,表示带有的行应该Class = 'ADJ'在所有其他行之前。然后在最后我们只抓取编号为 1 的行。结果是选择 ADJ 行,如果有一个ID,否则选择常规行。

根据更新的要求进行编辑
如果您有其他优先级标准,那么您可以将它们添加到 中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

在这里查看它的实际应用。

于 2012-11-07T21:18:53.693 回答