Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Case statement to find medal tally for each country

I have written the following query in SQL Server in order to find the medal tally for the countries based on the count of athletes winning a medal

SELECT 
    SUM(CASE WHEN MEDAL = 'G' THEN 1 ELSE 0 END) AS 'Gold',
    SUM(CASE WHEN MEDAL = 'S' THEN 1 ELSE 0 END) AS 'Silver',
    SUM(CASE WHEN MEDAL = 'B' THEN 1 ELSE 0 END) AS 'Bronze', 
    COUNT(*) AS total_medals, 
    TEAM
FROM 
    [dbo].[commonwealth games 2022 - players won medals in cwg games 2022]
GROUP BY 
    TEAM
ORDER BY 
    COUNT(*) DESC

Since for team sports such as hockey, each individual player’s medal is counting towards the tally, the count is becoming much higher than it is actually supposed to be. Is there a way I could modify the case statement or use a CTE or Window function to count a medal only once for a single event in case of a team sport.

The table I am using has 6 columns

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

ATHLETE_NAME, TEAM (country), SPORT, EVENT, MEDAL, CONTINENT

>Solution :

You could use a CTE (or derived table) to get the DISTINCT rows, and then aggregate:

WITH CTE AS(
    SELECT DISTINCT
           TEAM,
           SPORT,
           EVENT,
           MEDAL
    FROM [dbo].[commonwealth games 2022 - players won medals in cwg games 2022]) --I really suggest a better object name
SELECT SUM(CASE WHEN MEDAL = 'G' THEN 1 ELSE 0 END) AS Gold, --Don't use literal strings for aliases
       SUM(CASE WHEN MEDAL = 'S' THEN 1 ELSE 0 END) AS Silver,  --Don't use literal strings for aliases
       SUM(CASE WHEN MEDAL = 'B' THEN 1 ELSE 0 END) AS Bronze, --Don't use literal strings for aliases
       COUNT(*) AS total_medals,
       TEAM
FROM CTE
GROUP BY TEAM
ORDER BY COUNT(*) DESC;

Alternatively, you could get the TOP 1 per group and aggregate:

WITH CTE AS
    (SELECT TEAM,
            MEDAL,
            ROW_NUMBER() OVER (PARTITION BY TEAM, SPORT, EVENT, MEDAL ORDER BY ATHLETE_NAME) AS RN
     FROM [dbo].[commonwealth games 2022 - players won medals in cwg games 2022]) --I really suggest a better object name
SELECT SUM(CASE WHEN MEDAL = 'G' THEN 1 ELSE 0 END) AS Gold,
       SUM(CASE WHEN MEDAL = 'S' THEN 1 ELSE 0 END) AS Silver,
       SUM(CASE WHEN MEDAL = 'B' THEN 1 ELSE 0 END) AS Bronze,
       COUNT(*) AS total_medals,
       TEAM
FROM CTE
WHERE RN = 1
GROUP BY TEAM
ORDER BY COUNT(*) DESC;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading