2012-04-26 41 views
6

我很難做到這一點,無需搜索同一張表至少兩次以獲取最大行,然後獲取該行的值。有問題的桌子很大,所以這是不可接受的。返回行,每個組的最大值爲一列

這裏是我的表可能是什麼樣子:

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

這也可以在沒有子查詢:

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; 

否則這樣做。

+0

我喜歡它;很乾淨。 – Jeremy 2012-04-27 20:28:11

3

您在使用分析功能的正確軌道上。但你可能要像這樣與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 

如果可以有關係,你可能想使用row_number解析函數,而不是rank(即具有相同的idround行) - 將任意選擇兩個綁定行中的一個,使其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 
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