Reputation: 33
I've created a small database based on the Olympics for running a few sql queries from. I am trying to generate a table that displays each Country name and the total of Gold, Silver & Bronze medals won based on Athletes that are from these countries. Here is a screenshot of my Relational Model View:
Here is my query I am trying to run:
<h1>Olympics Database</h1>
<h3>Summary Information</h3>
<h4>Number of Olympic Athletes from United Kingdom</h4>
<?php
$conn = mysqli_connect('localhost', '#####', '#####') or die ('Could not connect:' . mysqli_error($conn));
echo 'Successfully Connected. <br/>';
mysqli_select_db($conn, '#####') or die('Database will not open');
echo 'Database Connected. <br/> <br/>';
$query2 = 'SELECT CountryAbbrev, (SELECT COUNT(CountryAbbrev) FROM athlete WHERE MedalID = 401 AND ath.CountryAbbrev = athlete.CountryAbbrev) AS Gold, (SELECT COUNT(CountryAbbrev) FROM athlete WHERE MedalID = 402 AND ath.CountryAbbrev = athlete.CountryAbbrev) AS Silver, (SELECT COUNT(CountryAbbrev) FROM athlete WHERE MedalID = 403 AND ath.CountryAbbrev = athlete.CountryAbbrev) AS Bronze FROM athlete AS ath';
$result2 = mysqli_query($conn, $query2) or die ('Invalid Query');
echo'<table><tr><th>Country Name</th><th>Gold</th><th>Silver</th><th>Bronze</th></tr>';
$row = mysqli_fetch_row($result2);
echo'<tr><td>' .$row[0].'</td><td>' .$row[1].'</td><td>' .$row[2].'</td><td>' .$row[3].'</td></tr>';
echo'</table>';
mysqli_close($conn);
?>
All I'm getting is invalid query. Going by my relation model view, could anyone help me figure out how I can display the total of gold, silver and bronze medals won by each country in a single table?
UPDATED: Here is a screenshot of the output:
Upvotes: 2
Views: 545
Reputation: 1562
In order to fix the "invalid query", you need a left join with medal
table, change the AND
s to OR
s, and use a group by
clause. Also, since you need the medal count, you need to replace SUM
with COUNT
. So you can do something like this:
SELECT CountryAbbrev as country, count(athlete.MedalID)
FROM athlete
LEFT JOIN medal on medal.MedalID = athlete.MedalID
WHERE MedalName = "Gold"
OR MedalName = "Silver"
OR MedalName = "Bronze"
GROUP BY CountryAbbrev;
This query outputs the total medal count (# gold + # silver + # bronze) for each country:
+---------+------------------------+
| country | count(athlete.MedalID) |
+---------+------------------------+
| AU | 4 |
| US | 5 |
+---------+------------------------+
If you want to print out the count of gold, silver, and bronze individually in difference columns, then you can use following query:
SELECT CountryAbbrev as country,
sum(if(MedalName = "Gold", 1, 0)) as Gold,
sum(if(MedalName = "Silver", 1, 0)) as Silver,
sum(if(MedalName = "Bronze", 1, 0)) as Bronze
FROM athlete
LEFT JOIN medal on medal.MedalID = athlete.MedalID
WHERE MedalName = "Gold"
OR MedalName = "Silver"
OR MedalName = "Bronze"
GROUP BY CountryAbbrev;
This query will output something like:
+---------+------+--------+--------+
| country | Gold | Silver | Bronze |
+---------+------+--------+--------+
| AU | 1 | 2 | 1 |
| US | 2 | 1 | 2 |
+---------+------+--------+--------+
And if you want to add a total column as well, try this query:
SELECT CountryAbbrev as country,
sum(if(MedalName = "Gold", 1, 0)) as Gold,
sum(if(MedalName = "Silver", 1, 0)) as Silver,
sum(if(MedalName = "Bronze", 1, 0)) as Bronze,
count(MedalName) as Total
FROM athlete
LEFT JOIN medal on medal.MedalID = athlete.MedalID
WHERE MedalName = "Gold"
OR MedalName = "Silver"
OR MedalName = "Bronze"
GROUP BY CountryAbbrev;
This query will output:
+---------+------+--------+--------+-------+
| country | Gold | Silver | Bronze | Total |
+---------+------+--------+--------+-------+
| AU | 1 | 2 | 1 | 4 |
| US | 2 | 1 | 2 | 5 |
+---------+------+--------+--------+-------+
I've ran these queries on my machine and they work as expected.
Upvotes: 0
Reputation: 739
Try this
SELECT c.CountryAbbrev,
(select count(a.MedalID) FROM athlete a WHERE c.CountryAbbrev=a.CountryAbbrev and a.MedalName = "Gold" ) as gold,
(select count(a.MedalID) FROM athlete a WHERE c.CountryAbbrev=a.CountryAbbrev and a.MedalName = "Silver" ) as Silver,
(select count(a.MedalID) FROM athlete a WHERE c.CountryAbbrev=a.CountryAbbrev and a.MedalName = "Bronze" ) as Bronze
from country as c
Upvotes: 0
Reputation: 13534
Your original SQL query returns invalid query due to you are selecting undefined field in a table. i.e athlete
table does not has a field named MedalName
.
You may use the following SQL query, by knowing the ids for each medal type, I supposed that they are 1,2,3 for Gold, Silver and Bronze respectively.
SELECT CountryAbbrev,
(SELECT COUNT(CountryAbbrev) FROM athlete WHERE MedalID = 1 AND ath.CountryAbbrev = athlete.CountryAbbrev) AS Gold,
(SELECT COUNT(CountryAbbrev) FROM athlete WHERE MedalID = 2 AND ath.CountryAbbrev = athlete.CountryAbbrev) AS Silver,
(SELECT COUNT(CountryAbbrev) FROM athlete WHERE MedalID = 3 AND ath.CountryAbbrev = athlete.CountryAbbrev) AS Bronze
FROM athlete AS ath
Sorry, it should be COUNT
instead of SUM
. Checkout the difference between SUM
and COUNT
from this link
Upvotes: 1