Oracle按id+type分组去重并查询所有列的实现方法
Oracle按id+type组合去重取整行的实现方案
需求说明
需要从表中返回所有字段,要求id+type的组合唯一,每组仅返回1行,非分组字段的取值无特殊要求。
现有测试表结构及数据如下:
| id | order | value | type | account |
|---|---|---|---|---|
| 1 | 1 | a | 2 | 1 |
| 1 | 2 | b | 1 | 1 |
| 1 | 3 | c | 4 | 1 |
| 1 | 4 | d | 2 | 1 |
| 1 | 5 | e | 1 | 1 |
| 1 | 5 | f | 6 | 1 |
| 2 | 6 | g | 1 | 1 |
现有方案验证
你当前编写的基于ROWID的方案是完全可行的:
SELECT ID, TYPE, VALUE, ACCOUNT FROM MYTABLE WHERE ROWID IN (SELECT MAX(ROWID) FROM MYTABLE GROUP BY ID, TYPE);
注:子查询中的
DISTINCT是多余的,GROUP BY后每组只会返回一个MAX(ROWID),不需要额外去重。
该方案逻辑简单,执行效率高,适合仅需要基础去重、无额外排序要求的场景。
更通用的窗口函数方案
如果后续可能需要调整每组的行选择规则(比如要求取order字段最大的行),更推荐使用ROW_NUMBER()窗口函数实现,扩展性更强:
SELECT ID, TYPE, VALUE, ACCOUNT, "order" FROM ( SELECT t.*, ROW_NUMBER() OVER(PARTITION BY id, type ORDER BY 1) rn FROM MYTABLE t ) WHERE rn = 1;
方案说明
PARTITION BY id, type按需要去重的组合分区,每个分区内的行属于同一个id+type组合- 因为对非分组字段取值无要求,
ORDER BY 1即可,如果你需要指定取某条规则的行,比如每个分组下order最大的行,只需要修改为ORDER BY "order" DESC即可 - 外层过滤
rn=1就可以取每个分区的第一行,实现去重效果
注意:
order是Oracle的保留关键字,作为字段名使用时需要加双引号包裹,避免语法报错。
内容的提问来源于stack exchange,提问作者JuniorGuy
相关产品推荐
相关产品推荐

