7

如果没有至少两次搜索同一个表以获取最大行,然后获取该行的值,我很难做到这一点。有问题的桌子很大,所以这是不可接受的。

这是我的表可能的样子:

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;

这行得通,但是效率很低(我必须手动过滤掉所有这些行,而我一开始就应该无法抓取这些行。)

我该怎么做才能获得正确的价值观?

4

3 回答 3

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小提琴。

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

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;

否则做同样的事情。

于 2012-04-26T23:04:58.473 回答
5

使用分析函数,您走在了正确的轨道上。但是你可能想要这样的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

如果可能存在关联(具有相同id和的行round),您可能希望使用row_number分析函数而不是rank-- 这将任意选择两个关联行中的一个以使 arnk为 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
于 2012-04-26T22:44:19.387 回答
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小提琴

于 2015-01-06T16:49:14.303 回答