Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sql Server: Rank by sum of points and order by ranking

Tags:

sql-server

I have a game table with these fields:

ID    Name       Email      Points
----------------------------------
1     John     [email protected]    120
2     Test     [email protected]     100
3     John     [email protected]    80
4     Bob      [email protected]     50
5     John     [email protected]    80

I want to group them by email (email Identifies that both players are the same no matter that row 2 and 4 have different names) and have also sum of points and the last entered name in the results and rank them with the heighest sum of points to the lowest

the Result I want from the sample table is:

Ranking     Name       Points   Games_Played      Average_Points 
------------------------------------------------------------------------------------------
 1          John        200         2                100
 2          Bob         150         2                75
 3          John        80          1                80

I could achieve getting ranking, sum of points, and average points but getting the last entered name I think need joining with the same table again and it seems a little wrong.

Any ideas how to do this?

like image 346
Ashkan Mobayen Khiabani Avatar asked Jun 23 '13 20:06

Ashkan Mobayen Khiabani


People also ask

What is difference between rank () row_number () and DENSE_RANK () in SQL?

The row_number gives continuous numbers, while rank and dense_rank give the same rank for duplicates, but the next number in rank is as per continuous order so you will see a jump but in dense_rank doesn't have any gap in rankings.

What is rank () over partition by?

The RANK() function is a window function that assigns a rank to each row in the partition of a result set. The rank of a row is determined by one plus the number of ranks that come before it. RANK() OVER ( PARTITION BY <expr1>[{,<expr2>...}]

What is DENSE_RANK SQL?

The DENSE_RANK() is a window function that assigns a rank to each row within a partition of a result set. Unlike the RANK() function, the DENSE_RANK() function returns consecutive rank values. Rows in each partition receive the same ranks if they have the same values.


2 Answers

Displaying the Name and grouping be email will cause to use e.g. MIN(Name) and lead to duplicate names.

Select Rank() over (order by Points desc) as Rank
,Name,Points,Games_Played,Average_Points
from
(
Select Min(Name) as Name,Email,Sum(Points) as Points
,Count(*) as Games_Played,AVG(Points) as Average_Points
From @a Group by Email
) a 
order by Rank

SQLFiddle

in the Fiddle are two commented lines you should uncomment to see the behavior on identical results.

like image 73
bummi Avatar answered Oct 11 '22 13:10

bummi


You can use Ranking Functions from SQL-Server 2005 upwards:

WITH Points 
     AS (SELECT Sum_Points = Sum(points) OVER ( 
                                 partition BY email), 
                Games_Played = Count(ID) OVER ( 
                                 partition BY email), 
                Average_Points = AVG(Points) OVER ( 
                                 partition BY email), 
                Rank = DENSE_RANK()  OVER ( 
                              Partition BY email Order By Points DESC),
                * 
         FROM   dbo.Game)
SELECT Ranking=DENSE_RANK()OVER(ORDER BY Sum_Points DESC), 
       Name, 
       Points=Sum_Points, 
       Games_Played,
       Average_Points
FROM   Points 
WHERE Rank = 1
Order By Sum_Points DESC;

DEMO

Note that the result is different since i'm showing the row with the highest point in case that the email is not unique, so "Test" instead of "Bob".

like image 29
Tim Schmelter Avatar answered Oct 11 '22 13:10

Tim Schmelter