MySQL Joining two queries for sports team - mysql

I am trying to display a list of teams with the number of goals they have scored (and order them by greatest to smallest) but am having trouble with joining all the queries together
Table 1: Teams
teamid teamname
1 team1
2 team2
3 team3
Table 2: Results
id gameid teamid gf
1 1 1 5
2 2 1 3
3 1 2 0
4 2 2 2
5 3 3 0
What I'm trying to achieve
1. Team1 8
2. Team2 2
3. Team3 0
Get list of all teams
SELECT team.teamid, team.teamname
FROM teams team
Gets sum of goals for 1 team
SELECT COALESCE( SUM( gf ) , 0 ) goalsfor
FROM results
WHERE teamid = 1
Joining of queries
SELECT team.teamid,
team.teamname,
COALESCE(res.gf, 0) goalsfor
FROM teams team
LEFT JOIN
(SELECT COALESCE(SUM(res.gf), 0) goalsfor
FROM results res
GROUP BY teamid) res ON team.teamid = res.teamid
ORDER BY goalsfor DESC
Been stuck on joining the queries all day

SELECT teams.teamname, res.goals FROM teams JOIN (
SELECT COALESCE(SUM(results.gf),0) AS goals, results.teamid AS teamid FROM results
group by results.teamid) res
ON teams.teamid=res.teamid ORDER BY goals DESC;

My solution is:
SELECT t.id,
t.name,
SUM(r.gf) goalsfor
FROM team t
LEFT JOIN
results r ON t.id = r.teamId
GROUP BY t.id
ORDER BY goalsfor DESC
My result from my dummy table:
id name goalsfor
1 Apple 8
2 Banana 2
3 Carrot 0
I don't think you need COALESCE if you made your columns have a default of 0 and cannot be null.

Related

Print the points table of a cricket match using Mysql

I am trying to solve this question using the join and nested queries. However I am facing issue while printing the final result as there are two rows which are not correctly printed. I am posting below question and the relevant details.
Sql query to fetch the Team name, total number of matches Played by each team, no of match won by the team and no of match lost by the team .
Below is Schema and sample data:
create table cricket(
Match_no int,
Team_a varchar(20),
Team_b varchar(20),
Winner varchar(20)
);
Insert into cricket (Match_no,Team_a,Team_b,Winner) values
(1,'westindies','srilanka' ,'westindies'),
(2 ,'india ','srilanka' ,'india'),
(3 ,'australia' ,'srilanka' ,'australia'),
(4 ,'westindies' ,'srilanka', 'srilanka'),
(5 ,'australia' ,'india' ,'australia'),
(6, 'westindies' ,'srilanka' ,'westindies'),
(7 ,'india' ,'westindies' ,'westindies'),
(8 ,'westindies' ,'australia', 'australia'),
(9 ,'westindies', 'india','india'),
(10,'australia', 'westindies', 'westindies'),
(11 ,'westindies' ,'srilanka' ,'westindies'),
(12 ,'india' ,'australia', 'india'),
(13, 'srilanka' ,'newzealand', 'srilanka'),
(14 ,'newzealand' ,'india', 'india')
I am using below query, but the matches won and lost is not correct for SriLanka and Newzeland in my output.
select team.t as Teamname,count(1)as Played ,
SUM(CASE WHEN team.t = c.Winner THEN 1 ELSE 0 end ) as WON,
(SUM(CASE WHEN team.t <> c.Winner THEN 1 ELSE 0 end ) ) as Lost
from
(select distinct Team_a as t from cricket where Team_a in (
select Team_b as t from cricket)) team
join cricket c on team.t in (c.Team_a,c.Team_b)
group by team.t order by 2 desc;
My output:
Teamname Played WON Lost
westindies 8 5 3
srilanka 7 2 5
india 6 4 2
australia 5 3 2
newzealand 2 0 2
Expected outcome:
Team_name No_of_matches_played Matches_won Matches_lost
westindies 8 5 3
india 6 4 2
australia 5 3 2
srilanka 7 1 6
newzealand 2 1 1
Any help will be highly appreciated.
You can unpivot an aggregate. The idea is:
select team, count(*), count(*), sum(is_win),
count(*) - sum(is_win) as num_losses
from ((select team_a as team,
(team_a = winner) as is_win
from cricket
) union all
(select team_b as team,
(team_b = winner) as is_win
from cricket
)
) c
group by team;
This assumes there are no ties. Your question says nothing about them.
Please try this :
select
t2.team,
t2.played as played ,
COALESCE (t3.won, 0) as won,
(t2.played - COALESCE (t3.won, 0)) as lost
from
(
select sum(cnt) as played, team
from
(
select count(1) as cnt, team_a as team
from cricket
group by team_a
union ALL
select count(1) as cnt, team_b as team
from cricket
group by team_b
) t1
group by team
) t2
left join
(
select count(1) as won, winner
from cricket group by winner
) t3
on t2.team = t3.winner
order by t3.won desc;

Rank standings table of soccer matches by H2H

Let me start explaining this with an example, I have a table with records of matches played in a soccer league, by using this table and its matches results am able to generate a standings table for the teams in this league via a mysql query.
Table [matches] (example)
--------------------------------------------------------
|id | hometeam |goalsfor|goalsagainst| awayteam |
--------------------------------------------------------
--------------------------------------------------------
| 8 | Real Madrid | 2 | 0 | Inter Milan |
--------------------------------------------------------
| 9 | Inter Milan | 3 | 3 | Real Madrid |
--------------------------------------------------------
Generated standings by query
Pos Team Pld W D L F A GD Pts
1 FC Barcelona 5 2 3 0 8 5 3 9
2 Inter Milan 6 2 2 2 11 10 1 8
3 Real Madrid 6 2 2 2 8 8 0 8
4 AC Milan 5 0 3 2 8 12 -4 3
The query:
select
team,
count(*) played,
count(case when goalsfor > goalsagainst then 1 end) wins,
count(case when goalsagainst> goalsfor then 1 end) lost,
count(case when goalsfor = goalsagainst then 1 end) draws,
sum(goalsfor) goalsfor,
sum(goalsagainst) goalsagainst,
sum(goalsfor) - sum(goalsagainst) goal_diff,
sum(
case when goalsfor > goalsagainst then 3 else 0 end
+ case when goalsfor = goalsagainst then 1 else 0 end
) score
from (
select hometeam team, goalsfor, goalsagainst from scores
union all
select awayteam, goalsagainst, goalsfor from scores
) a
group by team
order by score desc, goal_diff desc;
What I want to do is to order the standings based on Head to Head matches, so it would first order by points, then if there's a draw in points the second sorting would be to look at the two teams matches and compare who has more wins, or scored more than the other, then use that to sort the table.
By doing this as in the example Real Madrid will become ranked as 2nd and then Inter Milan as 3rd.
How can I achieve this?
I want to compare the two teams matches when they are equal in points, and use that to sort.
ORDER BY score DESC, h2h DESC; goal_diff DESC
Update: I ended going with a solution mix of sql and php, first I find equaled teams in rank, and then generate mini h2h standings for those team and update the rank based on it. I still see this doable with just sql, but with my heavy query its too complicated to implement with just sql, thats why I mixed with php in the implementation.
You need to process this in two steps. First, run the query above and store the results in a work table (call it work below). Then you need to get a tie breaker score for each team that is on the same score. Below, I join the matches table to the work table for each team, and ignore any where the work rows do not have the same score, as they are not important. Then give the team 1 if they won. Have to do it again for the other side. You might want to change this to the 3 for win, 1 for draw.
Sum these results up, join that result to the team row in work, and you have a tie break score for each row where where the score is the same.
You need to check what happens if you have many teams on the same score, and see if this is the result you want.
select w.*, b.hth
From work w
left outer join (
select team, SUM(hth) hth
from (
Select hometeam team, case when m.goalsfor > m.goalsagainst then 1 else 0 end hth
from matches m
inner join work w1 on m.hometeam = w1.team
inner join work w2 on m.awayteam = w2.team
where w1.score = w2.score
union all
Select awayteam team, case when m.goalsAgainst > m.goalsFor then 1 else 0 end hth
from matches m
inner join work w1 on m.hometeam = w1.team
inner join work w2 on m.awayteam = w2.team
where w1.score = w2.score
) a --all hth at same points
group by team
) b --summed to one row per team
on b.team = w.team
order by w.score desc, b.hth desc;

SQL distinct elements count in a group by same element

I have a problem to count distinct elements in a group by this element.
Let me explain this, I have two tables:
tb1
team amount
1 90
2 80
3 70
4 50
5 60
tb2
team player
5 1
1 1
3 2
1 2
2 2
1 3
3 3
4 3
5 3
2 4
The expected result is:
player nb_team Sum_amount nb_player
1 2 150 3
2 3 240 4
3 4 270 3
4 1 80 2
I'm doing this:
SELECT tb2.player, COUNT(DISTINCT tb1.team) as nb_team,
SUM(tb1.amount) AS sum,
(SELECT COUNT(DISTINCT tb2.player)
FROM tb2 where tb1.team=tb2.team) AS nb_player
FROM tb1, tb2
WHERE tb1.team=tb2.team
GROUP BY tb2.player
ORDER BY tb2.player ASC;
The 3 first columns are correct but I can't get the right value for nb_player.
I have to count how many players are included by the number of teams
For example for the first line result:
player 1 is playing in 2 teams that involved 3 players in total (player #1,#2 and #3)
any idea?
Counting teams and summing those teams amounts for a player needs a different resultset than counting players playing with given player in the same team. So I suggest using two different subqueries and then joining them on the player.
SELECT teams_total.player, teams_total.nb_team, teams_total.`sum`,
players_total.nb_players
FROM
( SELECT tb2.player, COUNT(DISTINCT tb1.team) as nb_team,
SUM(tb1.amount) AS `sum`
FROM tb1 JOIN tb2 ON tb1.team=tb2.team
GROUP BY tb2.player ) teams_total
JOIN
( SELECT tb2_1.player, COUNT(DISTINCT tb2_2.player) as nb_players
FROM tb2 tb2_1
JOIN tb1 ON tb2_1.team=tb1.team
JOIN tb2 tb2_2 ON tb2_2.team=tb1.team
GROUP BY tb2_1.player ) players_total
ON teams_total.player=players_total.player
ORDER BY teams_total.player ASC;
You can use the following query:
SELECT player,
COUNT(DISTINCT t2.team) AS nb_team,
SUM(amount) AS Sum_amount,
(SELECT COUNT(DISTINCT(player))
FROM tb2 AS t
WHERE INSTR(CONCAT(',',GROUP_CONCAT(DISTINCT t2.team), ','),
CONCAT(',',t.team,',')) <> 0) AS nb_player
FROM tb2 AS t2
INNER JOIN tb1 AS t1 ON t2.team = t1.team
GROUP BY player
GROUP_CONCAT is used in the correlated sub-query in order to get a comma separated list of all teams related to the player of the outer query. Using INSTR on this list, we can filter tb2 rows and count the DISTINCT number of players of these teams.
Demo here

MySQL - Select from two rows by a shared value where the query values are different

Very difficult to phrase this. Let me explain. I have a few tables: teams, games, and team_games. Team_games has a "standing" field which is 0'd by default. If standing is greater than 0, the game is finished and scores have been reported. I'm trying to come up with a query that will take two team IDs, and count the number of games they have in common where the standing is greater than zero.
Here's the table. So far I've done everything except for what I want.
Teams
---------------------
team_id team_name
---------------------
1 Test
2 Test 2
Games
---------------------
game_id start_time
---------------------
1 (unix)
2 -
3 -
Team Games
---------------------------------
game_id team_id standing
---------------------------------
1 1 1
1 2 2
2 1 2
2 2 1
3 1 1
3 2 2
So again, I want to capture just the rows where team_id is either 1 or 2, and the game id is the same, then count the unique game IDs.
So if I was looking for the number of games which were finished between team one and team two, the final result would be:
-----
COUNT
-----
3
SELECT COUNT(*) totalgames
FROM
(
SELECT Game_ID
FROM TeamGames
WHERE team_ID IN (1, 2) -- specify the teams here
GROUP BY Game_ID
HAVING COUNT(*) = 2 -- number of teams specified
AND SUM(standing = 0) = 0
) s
SQLFiddle Demo
OUTPUT
╔════════════╗
║ TOTALGAMES ║
╠════════════╣
║ 3 ║
╚════════════╝
i'm not sure but this may work
select count(distinct game_id) as games_number from Team_Games where (team_id = 1 or team_id = 2) and standing >= 1;
You can remove team from select clause and as well as group by, if you want.
SELECT T1.TEAM_ID, T2.TEAM_ID, COUNT(*)
FROM
TEAM_GAMES T1, TEAM_GAMES T2
WHERE T2.TEAM_ID <> T1.TEAM_ID
AND T2.GAME_ID = T2.GAME_ID
AND T1.STANDING > 0 AND T2.STANDING > 0
GROUP BY T1.TEAM_ID, T2.TEAM_ID

How to resolve this problem with aggregates and UNION in MySQL?

If my data is this
match homeTeam awayTeam homeTeamID awayTeamID homePoints awayPoints
1 Alpha Beta 1 2 4 2
2 Gamma Delta 3 4 6 0
3 Alpha Gamma 1 3 2 4
4 Delta Beta 4 2 3 3
I need to make a ladder for them but I can't get it just right
The results should look like this
Name played Points
Gamma 2 10
Alpha 2 6
Beta 2 5
Delta 2 3
So far my code looks like this
$query = "SELECT *
FROM (
SELECT homeTeam AS teamName,
COUNT(homeTeamID) AS matches_played,
SUM(if(homeTeamID, homePoints, 0)) AS total_points
FROM matches
UNION ALL SELECT awayTeam AS teamName,
COUNT(awayTeamID) AS matches_played,
SUM(if(awayTeamID, awayPoints, 0)) AS total_points
FROM matches
) all_points
GROUP BY teamName
ORDER BY total_points DESC ";
but all it did was show ALPHA played 4 games for 15 points and BETA played 4 games for 9 points - Gamma & Delta were gone :(
You do not have GROUP BY clause in inner query.
But it's still incorrect. try:
SELECT teamName, COUNT(*) AS played, SUM(points) as points
FROM (
SELECT homeTeam AS teamName,
homePoints AS points
FROM matches
UNION ALL SELECT awayTeam AS teamName,
awayPoints AS points
FROM matches
) all_points
GROUP BY teamName
ORDER BY total_points DESC