Selecting from 3 tables - mysql

I have the following tables below.
athletes
+------------+-----------------+---------------+-------------------------+
| idATHLETES | ATHLETENAME | TEAMS_idTEAMS | TEAMS_COUNTRY_idCOUNTRY |
+------------+-----------------+---------------+-------------------------+
| JG | JUSTIN GATLIN | USA-TF-MEN | USA |
| MS | MARIA SHARAPOVA | RUS-WTA | RUS |
| SW | SERENA WILLIAMS | USA-WTA | USA |
| UB | USAIN BOLT | JAM-TF-MEN | JAM |
| VW | VENUS WILLIAMS | USA-WTA | USA |
+------------+-----------------+---------------+-------------------------+
EVENTS
+------------+---------------+---------------------+------------------------+----------------------------------+
| idEVENTS | EVENTNAME | ATHLETES_idATHLETES | ATHLETES_TEAMS_idTEAMS | ATHLETES_TEAMS_COUNTRY_idCOUNTRY |
+------------+---------------+---------------------+------------------------+----------------------------------+
| ATH | ATHLETICS | JG | USA-TF-MEN | USA |
| ATH | ATHLETICS | UB | JAM-TF-MEN | JAM |
| TEN | TENNIS | MS | RUS-WTA | RUS |
| TEN | TENNIS | VW | USA-WTA | USA |
| TEN-DOUBLE | TENNIS DOUBLE | SW | USA-WTA | USA |
| TEN-DOUBLE | TENNIS DOUBLE | VW | USA-WTA | USA |
+------------+---------------+---------------------+------------------------+----------------------------------+
RESULTS
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+
| idRESULTS | STATUS | MEDALS | EVENTS_idEVENTS | EVENTS_ATHLETES_idATHLETES | EVENTS_ATHLETES_TEAMS_idTEAMS | EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY |
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+
| results1 | DID-NOT-WIN | SILVER | TEN | MS | RUS-WTA | RUS |
| results1 | WON | GOLD | TEN | VW | USA-WTA | USA |
| results2 | DID-NOT-WIN | BRONZE | ATH | JG | USA-TF-MEN | USA |
| results2 | WON | GOLD | ATH | UB | JAM-TF-MEN | JAM |
| results3 | WON | GOLD | TEN-DOUBLE | SW | USA-WTA | USA |
| results3 | WON | GOLD | TEN-DOUBLE | VW | USA-WTA | USA |
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+
How can I get a list Athletes who participate in more than one Event
and won at least one of them
and won none of them
I have come out with this code below but this returns the wrong output ?
SELECT idATHLETES, ATHLETENAME, EVENTNAME FROM athletes
JOIN EVENTS ON idATHLETES = ATHLETES_idATHLETES
JOIN RESULTS ON events.ATHLETES_idATHLETES = RESULTS.EVENTS_ATHLETES_idATHLETES
WHERE idEVENTS >=2 AND STATUS = 'WON'

Athletes who participated in more than one Event and won at least one of them:
select a.idATHLETES as id,a.ATHLETENAME as Name,count(*) as evtCount,
SUM(CASE WHEN r.STATUS = 'WON' THEN 1 ELSE 0 END) as victoryCount
from athletes a
join EVENTS e
on e.ATHLETES_idATHLETES = a.idATHLETES and e.ATHLETES_TEAMS_idTEAMS = a.TEAMS_idTEAMS and e.ATHLETES_TEAMS_COUNTRY_idCOUNTRY = a.TEAMS_COUNTRY_idCOUNTRY
join RESULTS r
on r.EVENTS_idEVENTS=e.idEVENTS and r.EVENTS_ATHLETES_idATHLETES=e.ATHLETES_idATHLETES -- etc
group by a.idATHLETES,a.ATHLETENAME
having evtCount>1 and victoryCount>0
order by a.idATHLETES,a.ATHLETENAME;
Results:
+----+----------------+----------+--------------+
| id | Name | evtCount | victoryCount |
+----+----------------+----------+--------------+
| VW | VENUS WILLIAMS | 2 | 2 |
+----+----------------+----------+--------------+
Athletes who participated in more than one Event and won none:
select a.idATHLETES as id,a.ATHLETENAME as Name,count(*) as evtCount,
SUM(CASE WHEN r.STATUS = 'WON' THEN 1 ELSE 0 END) as victoryCount
from athletes a
join EVENTS e
on e.ATHLETES_idATHLETES = a.idATHLETES and e.ATHLETES_TEAMS_idTEAMS = a.TEAMS_idTEAMS and e.ATHLETES_TEAMS_COUNTRY_idCOUNTRY = a.TEAMS_COUNTRY_idCOUNTRY
join RESULTS r
on r.EVENTS_idEVENTS=e.idEVENTS and r.EVENTS_ATHLETES_idATHLETES=e.ATHLETES_idATHLETES -- etc
group by a.idATHLETES,a.ATHLETENAME
having evtCount>1 and victoryCount=0
order by a.idATHLETES,a.ATHLETENAME;
Results:
no rows returned, you lack data for that
Notes
This is just a group by with having, and conditional aggregation (plus really messed up column names) :p

You can use having to get the records where there are at least two events and status = 'won' at least once.
SELECT idATHLETES, ATHLETENAME, EVENTNAME FROM athletes
JOIN EVENTS ON idATHLETES = ATHLETES_idATHLETES
JOIN RESULTS ON events.ATHLETES_idATHLETES = RESULTS.EVENTS_ATHLETES_idATHLETES AND RESULTS.Status = 'WON'
HAVING COUNT(idEVENTS) >=2 AND COUNT(STATUS) >= 1

Related

Not getting desired output in mysql

I am firing a query in mysql but not getting desired output.
this is the code:
select team_name,
sum(semis.points+final.points) as final_points
from semis
inner join final on semis.sid=final.sid
inner join teams on teams.tid=semis.tid
group by semis.tid
union
select team_name,
semis.Points
from semis
inner join teams on semis.tid=teams.tid
left join final on semis.sid=final.sid
where final.sid is null;
OUTPUT:
+-----------------------+--------------+
| team_name | final_points |
+-----------------------+--------------+
| BioTech & BioChem | 7 |
| Chemistry | 7 |
| Botany & Zoology | 7 |
| Physics & Electronics | 17 |
| BCA | 19 |
| BCOM | 11 |
| Gujarati | 10 |
| English | 10 |
| Economics | 20 |
| BCOM | 3 |
| Chemistry | 3 |
| English | 3 |
+-----------------------+--------------+
and the result i want to fetch
+-----------------------+--------------+
| team_name | final_points |
+-----------------------+--------------+
| BioTech & BioChem | 7 |
| Chemistry | 10 |
| Botany & Zoology | 7 |
| Physics & Electronics | 17 |
| BCA | 19 |
| BCOM | 14 |
| Gujarati | 10 |
| English | 13 |
| Economics | 20 |
+-----------------------+--------------+
Adding last 3 values to english,bcom,chemistry increasing it by 3 and making a total of BCOM: 14, Chemistry:10 , English: 13
From the sample data you posted and the expected results it looks like you can do it without UNION, by left joining final and with coalesce() for final.points:
select team_name, sum(semis.points + coalesce(final.points, 0)) as final_points
from semis
inner join teams on teams.tid=semis.tid
left join final on semis.sid=final.sid
group by semis.tid

MySQL selection based on AVG function

How can I select all Countries which won more than the average number of (any) medal across all countries from the table below:
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+---------------------------------+-------------------------+
| idRESULTS | STATUS | MEDALS | EVENTS_idEVENTS | EVENTS_ATHLETES_idATHLETES | EVENTS_ATHLETES_TEAMS_idTEAMS | EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY | EVENTS_VARIOUS_SPORTS_SPORTS_ID | awarded_medals_medal-id |
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+---------------------------------+-------------------------+
| results1 | DID-NOT-WIN | SILVER | TEN | MS | RUS-WTA | RUS | WOMENS_TENNIS | 2 |
| results1 | WON | GOLD | TEN | VW | USA-WTA | USA | WOMENS_TENNIS | 3 |
| results2 | DID-NOT-WIN | BRONZE | ATH | JG | USA-TF-MEN | USA | TRACK-AND-FIELD | 3 |
| results2 | WON | GOLD | ATH | UB | JAM-TF-MEN | JAM | TRACK-AND-FIELD | 1 |
| results3 | WON | GOLD | TEN-DOUBLE | SW | USA-WTA | USA | WOMENS_TENNIS | 3 |
| results3 | WON | GOLD | TEN-DOUBLE | VW | USA-WTA | USA | WOMENS_TENNIS | 1 |
+-----------+-------------+--------+-----------------+----------------------------+-------------------------------+-----------------------------------------+---------------------------------+-------------------------+
I am using this code :
CREATE VIEW `Countries_Athletes_who_wo_Gold` AS
select * from results where medals = 'Gold'
select EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY, medals from countries_athletes_who_wo_gold
where medals > (select AVG(medals) from countries_athletes_who_wo_gold) ;
but am not getting the required output?
You first need to write a query that counts the medals for each country.
SELECT EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY, COUNT(*) AS medal_count
FROM Countries_Athletes_who_wo_Gold
GROUP BY EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY
Then use this as a subquery twice in your query: once to get each country's medal count, and then to get the average across all countries.
SELECT *
FROM (
SELECT EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY, COUNT(*) AS medal_count
FROM Countries_Athletes_who_wo_Gold
GROUP BY EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY
) AS by_country
JOIN (SELECT AVG(medal_count) AS avg_medals
FROM (SELECT EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY, COUNT(*) AS medal_count
FROM Countries_Athletes_who_wo_Gold
GROUP BY EVENTS_ATHLETES_TEAMS_COUNTRY_idCOUNTRY) AS by_country
) AS all_countries
WHERE medal_count > avg_medals
DEMO

Selecting various values from an event

I have got these 3 tables below, i want to list all athletes who won Gold
Athletes
+------------+-----------------+
| athletesID | athletesName |
+------------+-----------------+
| jg | justin gatlin |
| ms | maria sharapova |
| ub | usain bolt |
| vw | venus williams |
+------------+-----------------+
events
+---------+-----------+---------------------+
| eventID | eventName | athletes_athletesID |
+---------+-----------+---------------------+
| ev1 | tennis | ms |
| ev1 | tennis | vw |
| ev2 | mens 100m | jg |
| ev2 | mens 100m | ub |
+---------+-----------+---------------------+
results
+-----------+--------+----------------+----------------------------+
| resultsID | Medal | events_eventID | events_athletes_athletesID |
+-----------+--------+----------------+----------------------------+
| results1 | silver | ev1 | ms |
| results1 | Gold | ev1 | vw |
| results2 | silver | ev2 | jg |
| results2 | Gold | ev2 | ub |
+-----------+--------+----------------+----------------------------+
I have used this code below so far but this lists all the silver medalists as having won Gold
SELECT
athletesID, athletesName, medal
FROM
myoly.athletes
JOIN
myoly.events ON athletes.athletesID = events.athletes_athletesID
JOIN
myoly.results ON myoly.events.eventID = myoly.results.events_eventID
WHERE
medal = 'gold';
How can I list all athletes who won Gold only ?
SELECT
a.athletesID,
a.athletesName,
r.medal
FROM results r
LEFT JOIN athletes a
ON a.athletesID = r.events_athletes_athletesID
WHERE r.medal = 'Gold';
If you remove your WHERE medal = 'gold' and look at your results, it should give you a clue about the problem. This is often the best way to troubleshoot.
Anyway, you need to join results to athletes on athleteID instead of eventID. This is because you're concerned with which athletes won gold not which events had a gold medal.
SELECT a.athletesID,
a.athletesName,
r.medal
FROM athletes a
INNER JOIN results r ON a.athletesID = r.events_athletes_athletesID
WHERE r.medal = 'Gold'

Multiple joins with MySQL, getting unexpected results

I am trying to join 3 tables but it looks like I am doing something wrong. Also I am not sure if INNER JOIN is a good idea here because there might be some missing corresponding rows in the other tables, but I would still like them to show up as NULL, then maybe LEFT JOIN would be better, but again, I'm doing something wrong.
A quick summary of the table responses:
SELECT geonameid, name, iso_alpha2, admin1_code
FROM maxmind_cities1000
WHERE name LIKE 'tron%' LIMIT 20;
+-----------+------------------------+------------+-------------+
| geonameid | name | iso_alpha2 | admin1_code |
+-----------+------------------------+------------+-------------+
| 1605268 | Tron | TH | 10 |
| 8949073 | Tronca | IT | 03 |
| 3107444 | Tronchón | ES | 52 |
| 8859151 | Tronconal | MX | 21 |
| 2821000 | Tröndel | DE | 10 |
| 3133880 | Trondheim | NO | 16 |
| 1252408 | Trongsa | BT | 21 |
| 2667264 | Trönninge | SE | 06 |
| 6535739 | Trontano | IT | 12 |
| 2971582 | Tronville-en-Barrois | FR | B2 |
| 3165134 | Tronzano Lago Maggiore | IT | 09 |
| 3165133 | Tronzano Vercellese | IT | 12 |
+-----------+------------------------+------------+-------------+
SELECT iso_alpha2, name
FROM maxmind_countryinfo
WHERE iso_alpha2 = 'NO';
+------------+--------+
| iso_alpha2 | name |
+------------+--------+
| NO | Norway |
+------------+--------+
SELECT code, name_local
FROM maxmind_admin1_codes_ascii
WHERE code = 'NO.16';
+-------+-----------------+
| code | name_local |
+-------+-----------------+
| NO.16 | Sør-Trøndelag |
+-------+-----------------+
So basically I am trying to join these three tables with this query, I have made a special case and said ON admin1.code = 'NO.16'
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
INNER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = 'NO.16'
WHERE city.name LIKE 'tron%' LIMIT 20;
but it gives me all the rows anyways instead of just Trondheim norway, so I am doing something wrong here. I tried switching to LEFT JOIN but get the same result set. I would like the city to show up in the result set even if there are no matching rows in maxmind_admin1_codes_ascii table, the admin code has the format iso_aplha2 '.' admin1_code
+---------+------------------------+--------------+-----------------+
| city_id | city_name | country_name | admin1_code |
+---------+------------------------+--------------+-----------------+
| 1605268 | Tron | Thailand | Sør-Trøndelag |
| 8949073 | Tronca | Italy | Sør-Trøndelag |
| 3107444 | Tronchón | Spain | Sør-Trøndelag |
| 8859151 | Tronconal | Mexico | Sør-Trøndelag |
| 2821000 | Tröndel | Germany | Sør-Trøndelag |
| 3133880 | Trondheim | Norway | Sør-Trøndelag |
| 1252408 | Trongsa | Bhutan | Sør-Trøndelag |
| 2667264 | Trönninge | Sweden | Sør-Trøndelag |
| 6535739 | Trontano | Italy | Sør-Trøndelag |
| 2971582 | Tronville-en-Barrois | France | Sør-Trøndelag |
| 3165134 | Tronzano Lago Maggiore | Italy | Sør-Trøndelag |
| 3165133 | Tronzano Vercellese | Italy | Sør-Trøndelag |
+---------+------------------------+--------------+-----------------+
This is my end result query but still don't understand why it gives me all results when I just want the special case 'NO.16'. And how should I structure my query if I want the cities to show regardless of there are no matching rows in the maxmind_admin1_codes_ascii table? This is what I have so far
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
INNER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = CONCAT(city.iso_alpha2, '.', city.admin1_code)
WHERE city.name LIKE 'tron%' LIMIT 20;
+---------+------------------------+--------------+--------------------+
| city_id | city_name | country_name | admin1_code |
+---------+------------------------+--------------+--------------------+
| 1605268 | Tron | Thailand | Uttaradit |
| 8949073 | Tronca | Italy | Calabria |
| 3107444 | Tronchón | Spain | Aragon |
| 8859151 | Tronconal | Mexico | Puebla |
| 2821000 | Tröndel | Germany | Schleswig-Holstein |
| 3133880 | Trondheim | Norway | Sør-Trøndelag |
| 1252408 | Trongsa | Bhutan | Tongsa |
| 2667264 | Trönninge | Sweden | Halland |
| 6535739 | Trontano | Italy | Piedmont |
| 2971582 | Tronville-en-Barrois | France | Lorraine |
| 3165134 | Tronzano Lago Maggiore | Italy | Lombardy |
| 3165133 | Tronzano Vercellese | Italy | Piedmont |
+---------+------------------------+--------------+--------------------+
This gives the result I want, but I don't think I am doing it right because the result was unexpected with the special case of 'NO.16'. Hope someone can help out!
Not totally sure if I understand what you are trying to do - but maybe this?
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
LEFT OUTER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = CONCAT(city.iso_alpha2, '.', city.admin1_code)
AND admin1.code = 'NO.16'
WHERE city.name LIKE 'tron%' LIMIT 20;
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
INNER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = city.admin1_code
WHERE city.name LIKE 'tron%' LIMIT 20 AND city.admin1_code = 'NO.16';

Counting multiple entries / statistics

I want to add a survey to a website. And a good survey needs a reporting. Some basic reports are done. Now I want to put some cream on the coffee ...
The table with sample data:
mysql> select * from u001;
+----+----------+------------+-------+---------------------+
| id | drink | sex | age | date |
+----+----------+------------+-------+---------------------+
| 1 | Beer | m | 30-39 | 2012-10-17 23:17:52 |
| 2 | Milk | f | 10-19 | 2012-10-18 00:15:59 |
| 3 | Milk | f | 20-29 | 2012-10-18 23:33:07 |
| 4 | Tea | m | 30-39 | 2012-10-20 22:47:08 |
| 5 | Water | f | 20-29 | 2012-10-20 22:47:30 |
| 6 | Milk | m | 30-39 | 2012-10-20 22:51:22 |
+----+----------+------------+-------+---------------------+
6 rows in set (0.00 sec)
I want to get a result that counts how many women/men likes Tea/Beer/etc.
A desired result like this:
+-------+-----+---------+
| drink | sex | counted |
+-------+-----+---------+
| Beer | m | 1 |
| Milk | f | 2 |
| Tea | m | 1 |
| Water | f | 1 |
| Milk | m | 1 |
+-------+-----+---------+
Have anyone some suggestions or solutions?
Thanks in advance.
SELECT drink, sex, COUNT(id) counted
FROM u001
GROUP BY drink, sex
SQLFiddle Demo
select drink, sex, count(id) from u001 group by drink, sex