查询实现组中的最大行数?

时间:2016-08-09 09:16:07

标签: sql oracle

我有一张表如下:

id  |   name    |   score
-------------------------
1   |   Alex    |    10
2   |   Jim     |    20
3   |   Ming    |   12
4   |   Alex    |   15
5   |   Alex    |   17
6   |   Ming    |   11

我想要一个包含以下结果的查询:

id  |   name    |   score
-------------------------
5   |   Alex    |    17
2   |   Jim     |    20
3   |   Ming    |   12

是否有任何解决方案可以通过查询获得上述结果?

2 个答案:

答案 0 :(得分:1)

你可以试试这个:

Running

答案 1 :(得分:1)

row_number()方法相比,这在记忆方面更有效。

with test(id, name, score) as (
  select 1,'Alex',10 from dual union all
  select 2,'Jim',20 from dual union all
  select 3,'Ming',12 from dual union all
  select 4,'Alex',15 from dual union all
  select 5,'Alex',17 from dual union all
  select 6,'Ming',11 from dual
)
select max(id) keep ( dense_rank first order by score desc, id asc) id, name, max(score) score
from test
group by name;

为了演示效率,您可以在任何Oracle数据库中运行这两个查询:

查询#1 - row_number方法

select object_id, object_type, last_ddl_time from 
(select row_Number() over ( partition by object_type order by last_ddl_time desc, object_id asc) rn, object_id, object_type, last_ddl_time from dba_objects ) 
where rn = 1;

查询#2 - max() keep方法

select max(object_id) keep ( dense_rank first order by last_ddl_time desc, object_id asc) object_id, object_type, max(last_ddl_time)
from dba_objects
group by object_type;

在我的数据库中,两个查询都需要188,000个缓冲区。但是查询#1需要28兆内存来执行,而查询#2几乎不需要。在运行每个查询几次之后(为了公平 - 将所有内容都放入缓冲区),查询#2运行得稍快(3.52秒对5.11秒)。但很多事情都会影响挂钟运行时间。相对内存使用量是更引人注目的数据。

没有ORACLE功能

with test(id, name, score) as (
  select 1,'Alex',10 from dual union all
  select 2,'Jim',20 from dual union all
  select 3,'Ming',12 from dual union all
  select 4,'Alex',15 from dual union all
  select 5,'Alex',17 from dual union all
  select 6,'Ming',11 from dual
)
SELECT t1.id, t1.name, t1.score
from test t1
where not exists ( SELECT 'higher score, or higher ID if same score, for the same name'
                   FROM test t2
                   WHERE t2.name = t1.name
                   AND   ( t2.score > t1.score OR ( t2.score = t1.score AND t2.id > t1.id ) ) );