这似乎是一个非常简单的问题,但我现在似乎无法弄明白......
以下是我从当前存储过程中获取的数据的简化视图:
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
请帮忙!
更新
我刚刚意识到这个查询还有一个额外的要求;如果有两个调整,其中一个有“坏债”的描述而另一个有“已取消”,则需要选择带有“已取消”描述的记录(参见上面的更新数据)。
答案 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