0

I'm using PostgreSQL.
I have a table competitor with information about a competitor in an e-sports game. The table contains gameID, the competitor's nick and name of the character he/she played.

I want to select every nick and the character they have played the most.
For example, if the competitor Faker has played the character Ryze 4 times and Lulu 3 times, I want Faker Ryze 4 to be in the output.

This is what I have so far:

select nick, character, count(*) as played
from competitor
group by nick, character
order by nick;

But then I get both Faker Ryze 4 and Faker Lulu 3 in the output.
I've tried with max() and nesting, but I can't figure it out.

3 Answers 3

2

This will do the trick.

SELECT nick, character,played
FROM
  (SELECT s1.*,
          row_number() OVER (PARTITION BY nick
                             ORDER BY played DESC) AS row1
   FROM
     (SELECT nick, character, COUNT(*) AS played
      FROM competitor
      GROUP BY nick, character
      ORDER BY nick,
               COUNT(*) DESC) s1)s2
WHERE row1=1;

The query is 100% correct. SQL Fiddle here. Also, it is the only query that will easily support ties for the same nick (by changing row_number() with rank()) and avoids unnecessary JOIN.

Sign up to request clarification or add additional context in comments.

6 Comments

this will result in all counts. you are computing max on nick and character witch were already unique after the nested select.
I'm afraid not. This does exactly the same as the query I had from before.
@MartinJohansen Fixed it.
You are making the same mistake. you are partitioning by nick and character, witch are already unique from the inner select (s1). All row1 will be "1".
I see "PARTITION BY nick, character"
|
1

Try this:

with counts as (
    select nick, character, count(*) cnt, max(sometimestamp) hora
    from competitor
    group by nick, character
    order by nick, cnt desc, hora
)


select nick, character, max(cnt)
from counts c1 where nick
in (select nick from counts where nick = c1.nick limit 1)
    and character in (select character from counts where nick = c1.nick limit 1)
group by nick, character
order by nick

max(sometimestamp) hora will be the tie breaker, you will have to adapt. Or if you don't care for ties just remove this field. This query will give you the character for each nick, with the bigger count, and, in case of tie, it will return the first one to reach the max count.

1 Comment

Thank you very much. This worked perfectly! I didn't even know about WITH statements.
0

You are going down the right route with max and nesting, I have slightly modified an answer given here:

select t1.nick, t1.character, t1.count
from (
    select nick, character, count(*) as played
    from competitor
    group by nick, character
) t1
inner join
(
  select nick, max(played) max_count
  from 
  (
    select nick, character, count(*) as played
    from competitor
    group by nick, character
  )
  group by nick
) t2
  on t1.nick = t2.nick
  and t1.count = t2.max_count

This might be easier to read if you created a view for the base query:

View called PlayerCount:

select nick, character, count(*) as played
from competitor
group by nick, character

And the SQL query is now:

select t1.nick, t1.character, t1.count
from PlayerCount t1
inner join
(
  select nick, max(played) max_count
  from PlayerCount
  group by nick
) t2
on t1.nick = t2.nick
and t1.count = t2.max_count

2 Comments

i get this error: ERROR: aggregate functions are not allowed in JOIN conditions LINE 15: and t1.count = t2.max_count;
ah yeah sorry I left in the name of the dummy table I tested it on, I have modified it now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.