返回每组最大值为一列的行

时间:2012-04-26 22:39:08

标签: sql oracle max greatest-n-per-group

我很难在没有搜索同一个表至少两次以获取最大行的情况下执行此操作,然后获取该行的值。有问题的表格很大,所以这是不可接受的。

这是我的表格的样子:

SCORES
ID    ROUND    SCORE
1     1        3
1     2        6
1     3        2
2     1        10
2     2        12
3     1        6

我需要返回每个ID在最近一轮中获得的分数。也就是说,行具有最大(圆形),但不是最大分数。

OUTPUT:
ID   ROUND   SCORE
1    3       2
2    2       12
3    1       6

现在我有:

SELECT * FROM 
(SELECT id, round,
CASE WHEN (MAX(round) OVER (PARTITION BY id)) = round THEN score ELSE NULL END score
 FROM
 SCORES
 where id in (1,2,3)
) scorevals
WHERE
scorevals.round is not null;

这有效,但效率很低(我必须手动过滤掉所有这些行,当我应该首先不能抓住那些行时。)

我能做些什么来获得正确的价值观?

3 个答案:

答案 0 :(得分:7)

没有子查询也可以这样做:

SELECT DISTINCT
       id
      ,max(round) OVER (PARTITION BY id) AS round
      ,first_value(score) OVER (PARTITION BY id ORDER BY round DESC) AS score
FROM   SCORES
WHERE  id IN (1,2,3)
ORDER  BY id;

准确地返回您要求的内容 关键点是在窗口函数之后应用了DISTINCT

SQL Fiddle.

可能更快,因为它使用相同的窗口两次:

SELECT DISTINCT
       id
      ,first_value(round) OVER (PARTITION BY id ORDER BY round DESC) AS round
      ,first_value(score) OVER (PARTITION BY id ORDER BY round DESC) AS score
FROM   SCORES
WHERE  id IN (1,2,3)
ORDER  BY id;

否则也这样做。

答案 1 :(得分:4)

您使用分析功能走在正确的轨道上。但是你可能想要rank函数

这样的东西
SELECT *
  FROM (SELECT a.*,
               rank() over (partition by id order by round desc) rnk
          FROM scores
         WHERE id IN (1,2,3))
 WHERE rnk = 1

如果可以存在关联(具有相同idround的行),您可能希望使用row_number解析函数而不是rank - 这将任意选择两个绑定行中的一个,使rnk为{1},而不是将rank作为MAX返回。

如果您想使用SELECT * FROM (SELECT a.*, MAX(round) OVER (partition by id) max_round FROM scores WHERE id IN (1,2,3)) WHERE round = max_round 分析函数,您还可以执行类似

的操作
{{1}}

答案 2 :(得分:0)

对于这类问题,我倾向于使用max...keep...dense_rank构造:

select
  id,
  max(round)  round,
  max(score) keep (dense_rank last order by round) score
from
  tq84_scores
group by
  id;

sql fiddle