2012-04-26 10 views
6

Tôi đang gặp khó khăn khi thực hiện việc này mà không cần tìm kiếm cùng một bảng ít nhất hai lần để lấy hàng tối đa và sau đó lấy giá trị cho hàng đó. Bảng được đề cập khá lớn nên không thể chấp nhận được.Hàng trả về có giá trị lớn nhất của một cột cho mỗi nhóm

Đây là những gì bàn của tôi có thể trông giống như:

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

Tôi cần phải trả lại số điểm mỗi ID có trong vòng gần đây nhất. Đó là, hàng có tối đa (tròn), nhưng không phải là số điểm tối đa.

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

Ngay bây giờ tôi có:

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; 

này hoạt động, nhưng là khá hiệu quả (tôi phải tự lọc ra tất cả các hàng, khi tôi chỉ có thể không lấy những hàng trong nơi đầu tiên.)

Tôi có thể làm gì để có được các giá trị phù hợp?

Trả lời

4

Đây cũng là tốt mà không subquery:

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; 

Returns chính xác những gì bạn yêu cầu.
Điểm quan trọng là DISTINCT được áp dụng sau chức năng cửa sổ.

SQL Fiddle.

lẽ nhanh hơn vì nó sử dụng cùng một cửa sổ hai lần:

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; 

Nếu không làm như vậy.

+0

tôi thích nó; rất sạch sẽ. – Jeremy

3

Bạn đang đi đúng hướng bằng chức năng phân tích. Nhưng có thể bạn muốn một cái gì đó như thế này với các chức năng 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 

Nếu có thể có mối quan hệ (các hàng có cùng idround), bạn có thể muốn sử dụng row_number chức năng phân tích thay vì rank - đó sẽ tùy tiện chọn một trong hai hàng được gắn để có một số rnk của 1 thay vì trả lại cả hai là rank.

Nếu bạn muốn sử dụng MAX chức năng phân tích, bạn cũng có thể làm điều gì đó như

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

Đối với loại vấn đề, tôi có xu hướng sử dụng max...keep...dense_rank xây dựng:

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

sql fiddle