Reputation: 11
I'm on this exercise:
Create a single routine that sums up all the points scored by players of each class, displays the result with the sum and the group name ordered from highest to lowest, and finally adds two points to the first group and one point to the second group.
and I'm having a lot of trouble making sense and getting somewhere with the "finally adds two points to the first group and one point to the second group". I assume it's asking to add 2 to the top 1 score and add 1 to the top 2 score, the problem is I can't figure out how to do that.
I've only managed to get to the following point:
CREATE PROCEDURE total_scores()
SQL SECURITY DEFINER
BEGIN
SELECT SUM(scores) AS 'total scores', class
FROM players
GROUP BY class
ORDER BY SUM(scores) DESC LIMIT 2 OFFSET 0;
END //
Upvotes: 1
Views: 41
Reputation: 98398
This is pretty straightforward. Here I'm using class to disambiguate ties:
select
score_sum + case ranking when 1 then 2 when 2 then 1 end score,
class
from (
select
class,
sum(scores) score_sum,
row_number() over (order by sum(scores) desc, class) ranking
from players
group by class
) class_scores
where ranking < 3
order by score desc
Most cases of doing more complicated things with ties can be handled by replacing row_number()
with rank()
or dense_rank()
and changing the case statement and possibly removing the where condition and adding a limit to the outer query. Details depend on what you want.
Upvotes: 0
Reputation: 76943
Actually you need all groups and to add 2 to the first place and 1 to the second place. I will give you only a query (untested, as you gave no schema nor sample data):
WITH rankings AS
(
SELECT SUM(scores) AS 'total_scores', class
FROM players
GROUP BY class
)
SELECT total_scores +
CASE
WHEN COUNT(*) = 1 THEN
CASE
WHEN MAX(better.class) IS NULL THEN 2
ELSE 1
END
ELSE 0
END
as 'total scores',
class
FROM rankings current
LEFT JOIN rankings better
ON current.class <> better.class AND
current.total_scores <= better.total_scores
GROUP BY current.class
If there are typos or other mistakes, then let me know and we can fix it.
Explanation:
rankings
select
from players
class
sum
the scores
and for the space of this definition we do not add the bonus points yet and we select
class
tooselect
from rankings
and we alias it as current
left join
with rankings
, aliased as better
on
the criteria that their class
does not matchand
current.total_scores <= better.total_scores
current.class
, so from now on aggregates can be usedselect
clause
total_scores
better.class
is always null
, then we add 2total scores
, as you preferredclass
tooNote that this allows ties, but, if there is a tie of three, then none of them will get extra points, whereas if there is a single winner but a tie at second place, then only the winner gets extra points, if there is a tie of two, then each of them gets one extra point, otherwise the first place gets 2 extra points and the second place gets 1 extra point.
Upvotes: 0