I'm trying to compare two soccer players who played in the same team and I'm trying to know who scored more goals in each game they played together and COUNT the number of times a player scored more goals than the other in each game. For example:
Game 1: Messi 2 goals - Neymar 0 goals
Game 2: Messi 2 goals - Neymar 3 goals
Game 3: Messi 4 goals - Neymar 1 goal
The final result should be Messi = 2 , because he scored more goals in 2 games.
I have the next query to find the players who share the same team and game with my chosen player (Messi in this example):
SELECT S1.Team, S1.Game, S1.Player, S2.Team, S2.Game, S2.Player
FROM Mytable S1
INNER JOIN Mytable S2 ON S1.Team = S2.Team AND
S1.Game= S2.Game AND
S1.Player LIKE '".mysql_real_escape_string($Messiinthiscase)."'
AND S2.Player <> '".mysql_real_escape_string($Messiinthiscase)."';
Mytable is like:
Player | Team | Game | Goals
-------------------------------
Messi A G1 2
Neymar A G1 0
Messi A G2 2
Neymar A G2 3
Messi A G3 4
Neymar A G3 1
but I don't know how to implement a COUNT to compare both players. Probably it is a stupid question with an easy answer but I've been hours working on it and nothing comes to my mind.
Thanks for all your help
Although a strange query in itself, lets see if this helps. You are on a good track, and as you stated, it is another TEAM-MATE who PLAYED IN the same game... So you need a SUM() based on a case/when grouped by your "Messi" player and whoever else played and scored... THEN apply a HAVING. So, if Messi had 5 team-mates, there should be 4 possible returns
Messi vs Team-mate 1
Messi vs Team-mate 2
Messi vs Team-mate 3
Messi vs Team-mate 4
and of those, Messi may have scored more than team-mates 1, 2 and 4, but less than 3.
SELECT
S1.Team,
S1.Player,
S2.Player,
sum( case when s1.goals > s2.goals then 1 else 0 end ) as Player1Higher,
sum( case when s1.goals < s2.goals then 1 else 0 end ) as Player1Lower
FROM
Mytable S1
INNER JOIN Mytable S2
ON S1.Team = S2.Team
AND S1.Game = S2.Game
AND NOT S1.Player = S2.Player
WHERE
S1.Player LIKE '".mysql_real_escape_string($Messiinthiscase)."'
GROUP BY
S1.Team,
S1.Player,
S2.Player
HAVING
sum( case when s1.goals > s2.goals then 1 else 0 end ) >
sum( case when s1.goals < s2.goals then 1 else 0 end )
Notice the WHERE clause has your criteria for "Messi" string, and the JOIN clause just says player 1 (Messi) IS NOT the same for player 2.
The group by is NOT including the EACH GAME as you want the total based on games that the players both played in...
Finally the having includes the final "keep only these records" where the sum of player 1 goals exceeds the sum of player 2 goals.
If you remove the HAVING clause, you would see your results that Messi had 2 games higher goals and 1 game LESS goals compared to player Neymar
The comparisons do NOT consider "=" as neither player had MORE points than the other... so if such a game where BOTH people scored 2 points, then neither would be considered the higher scoring player.
The comparison could be simplified even more by doing
sum( case when s1.goals = s2.goals then 0
when s1.goals > s2.goals then 1 else -1 end ) as NetGames
So, again, if the score is tied, then nobody is better. If s1 goals are higher, +1, otherwise the other player was higher, -1. If the Net Games is positive, then player 1 was better player, = 0 tie, negative is other player better.
SELECT S1.Team, S1.Game, S1.Player, S2.Team, S2.Game, S2.Player, CASE WHEN S1.goals < S2.goals THEN S2.goals - S1.goals WHEN S2.goals < S1.goals THEN S1.goals - S2.goals ELSE 0 END as difference
FROM Mytable S1
INNER JOIN Mytable S2 ON S1.Team = S2.Team AND
S1.Game= S2.Game AND
S1.Player LIKE '".mysql_real_escape_string($Messiinthiscase)."'
AND S2.Player <> '".mysql_real_escape_string($Messiinthiscase)."';
Related
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;
I have table like this:
home | away | home_round_1 | away_round_1 | home_round_2 | away_round_2
team1 team2 20 10 5 -2
team3 team1 1 2 -11 4
team2 team3 20 -1 -1 10
I'm trying to figure out how to calculate wins, loses, evens and average game result group by teams. Game result sit counted as home round 1 + round 2 or away round 1 + round 2 and winner is team that has less points in the end. I have made counter that count certain teams average in mysql with cases but is it possible to count all this inside mysql, that it will count values by team.
So far I have manage to count team avrage with this:
SELECT
AVG(
CASE
WHEN home = "team1" THEN home_round_1 + home_round_2
WHEN away = "team1" THEN away_round_1 + away_round_2
ELSE NULL
END
) AS 'Avrage_points'
FROM
`Game_results`
/*-------------temp table--------------*/
CREATE TEMPORARY TABLE IF NOT EXISTS bowlpick.tempschedule AS
(SELECT * FROM bowlpick.schedule
where season = (select max(year) from bowlpick.season));
/*-------------temp table--------------*/
set #g1= (select winner from bowlpick.tempschedule where game =1);
select date,name, #g1,bowl1 Pick,comf1
,case
when bowl1 = #g1 then comf1
when bowl1 <> #g1 then -comf1
else '0' end pts
from bowlpick.picks
where year(date) = (select max(year) from bowlpick.season)
order by bowl1 desc limit 5
<--------------------Table----------------->
name #g1 Pick comf1 pts
Player 1 Boise State Washington 7 -7
Player 2 Boise State Boise State 30 -30
Player 3 Boise State Boise State 21 -21
Player 4 Boise State Boise State 27 -27
Player 5 Boise State Boise State 15 -15
Why does this not work??? The last four pts should be positive numbers, not negative.
It as if the variable (#g1) is not working in the 'CASE' part. It works correctly when the 'select' part.
If I hard-code the winner (Boise State), it works correctly. Does variables not work in case statements?
Not sure why you are using temporary tables, you could do it in a single query, see the following example for somewhere to start, one other thing I noticed was that the case was returning numbers for the two case statements and a string for the else. Not only this the case statement has 2 WHEN statements which cover all bases surely meaning '0' would have never been selected anyway.
SELECT
bowlpick.picks.date
,bowlpick.picks.name
,bowlpick.tempschedule.winner
,bowlpick.picks.bowl1 Pick
,bowlpick.picks.comf1
,CASE
WHEN bowlpick.picks.bowl1 = bowlpick.tempschedule.winner THEN bowlpick.picks.comf1
WHEN bowlpick.picks.bowl1 <> bowlpick.tempschedule.winner THEN -bowlpick.picks.comf1
ELSE 0
END pts
FROM
bowlpick.picks
LEFT JOIN bowlpick.tempschedule ON year(bowlpick.picks.date) = bowlpick.tempschedule.season
WHERE
bowlpick.tempschedule.game =1
ORDER BY
bowl1 DESC
LIMIT 5
The following is an additional bit of work removing the need for the temporary table (links and grouping would need better defining but with an incomplete schema it's the best I could do)
SELECT
p.Date
,p.Name
,s.Winner
,p.Bowl1 Pick
,p.Comf1
,CASE
WHEN p.Bowl1 = s.Winner THEN p.Comf1
WHEN p.Bowl1 <> s.Winner THEN -p.Comf1
ELSE 0
END pts
FROM
picks p
LEFT JOIN schedule s ON YEAR(p.Date) = s.Season
WHERE
s.game = 1
GROUP BY
s.Season, p.Date
HAVING
s.Season = MAX(s.Season)
ORDER BY
p.Bowl1 DESC
LIMIT 5
He's my SQL Fiddle used to do this
I am building a Hockey Sports score and prediction system using PHP/MySQL. Below are the system design.
I have a GAMES table where two team numbers and their score in the game is present.The columns from this table are as below.
ID ---- TEAM1 ---- SCORE1 ---- TEAM2 ---- SCORE2
1 70 1 73 2
2 74 0 70 1
3 74 0 73 0
I also have a PICKS table where the details related to user's game predictions are present. Users can guess which team will win in a game and that data is stored in this table. The columns from this table are as below. Each user can guess only once for each game.
ID ---- GAME ---- USER ---- TEAM ---- POINT
1 1 1 70 1
2 2 1 70 1
3 3 1 73 1
3 1 2 70 1
Based on the above available data, I am trying to build up the result where each user (column USER) should be awarded the points(column POINT) for each correct guess. The guess can be validated based on the scores from GAMES table. The final output should be like as below.
USER ---- POINTS ---- CORRECT GUESS COUNT ---- WRONG GUESS COUNT
1 1 1 2
2 0 0 1
The columns "CORRECT GUESS COUNT" and "WRONG GUESS COUNT" represent the total number of correct guess and wrong guess done by the user.
I have created a SQL Fiddle for the above tables with some sample data.
http://sqlfiddle.com/#!2/8d469/4/0
EDIT:
Some more inforamtion are below. It's possible that a game can be a
draw.
In that case the score will be 0 for each team. When a game is
draw, users get no points.
SELECT p.user,
SUM(IF(g.id IS NOT NULL, p.point, 0)) As points,
SUM(IF(g.id IS NOT NULL, 1, 0)) Correct,
SUM(IF(g.id IS NULL, 1, 0)) Wrong
FROM Games g
RIGHT JOIN Picks p ON g.id = p.game AND
p.team = IF(g.score1 > g.score2 , g.team1, IF(g.score1 < g.score2, g.team2, NULL))
GROUP BY p.user;
SQL Fiddle (with your data)
You'll have to forgive me, if there is a more MySQL way to do it than this (background is Oracle/SQL Server):
SELECT
p.user
,sum(CASE
WHEN p.team = g.winner THEN point ELSE 0 END) points
,sum(CASE
WHEN p.team = g.winner THEN 1 ELSE 0 END) good_guess
,sum(CASE
WHEN p.team <> g.winner THEN 1 ELSE 0 END) bad_guess
FROM
picks p
INNER JOIN (
SELECT
id game_id
,CASE
WHEN score1 > score2 THEN team1
WHEN score2 > score1 THEN team2
ELSE -1 --no team_id as negative
END winner
FROM
games
) g
ON
g.game_id = p.game
GROUP BY
p.user
This is a bit of a complex query, but I have a database of snooker matches, and am trying to generate stats on who has played and won the most deciding frames (don't worry about the rules if you don't know the game).
Table:
ID player1 player2 bestOf player1Score player2Score
1 1 2 9 5 0
2 2 1 9 5 4
3 1 2 9 5 4
4 2 1 9 4 5
What I am trying to do is something like the following:
SELECT COUNT(*) AS played, DISTINCT(player1,player2) AS playerID
FROM matches
WHERE (player1Score=BestOf / 2 + 0.5 AND player2Score=BestOf / 2 - 0.5)
GROUP BY playerID
The above query doesn't work, as I believe DISTINCT doesn't support multiple columns. The result I'm looking for from the top table is:
playerID played won
1 3 2
2 3 1
The top row in the table is not displayed, as it is not a final frame.
I have tried variations such as:
SELECT GROUP(player1,player2)
SELECT player1 + player2 AS playerID, select DISTINCT(playerID)
SELECT (player1 + player2) AS playerID GROUP BY playerID
and a good few others. Any hint would be appreciated!
I don't actually have your tables with me so my sql probably has lots of syntax errors. But hopefully I will be to get the general idea across.
We can compute the list of deciding frame games where player1 won and union it with the list of deciding frame games where player2 won. As long as we rename the winner's column name to the same string ('player'), the union of these tables should yield a single table marking out the number of times each person won.
select player, count(*) as num_won from ((select player1 as player from matches where player1Score - player2Score = 1) union (select player2 as player from matches where player2Score - player1Score = 1));
This should give you a mapping from each player's id to the number of times they won.
Then consider
select player, count(*) as num_played from ((select player1 as player from matches where abs(player1Score - player2Score) = 1) union (select player2 as player from matches where abs(player2Score - player1Score) = 1));
The use of the abs function should help you discover the number of deciding frame games each player played. Now we combine these two tables to get your final answer
select players_table.player, players_table.num_played, winners_table.num_won from (select player, count(*) as num_won from ((select player1 as player from matches where player1Score - player2Score = 1) union (select player2 as player from matches where player2Score - player1Score = 1)) winners_table), (select player, count(*) as num_played from ((select player1 as player from matches where abs(player1Score - player2Score) = 1) union (select player2 as player from matches where abs(player2Score - player1Score) = 1)) players_table) where winners_table.player == players_table.player;
create table temp_score
select playerid, count(*) as won
FROM(
Select case when player1score > player2score then player1 else player2 end as playerid
from score
where
(player2Score=Round(BestOf / 2 + 0.5,0) AND player1Score=round(BestOf / 2 - 0.5,0))
or
(player1Score=Round(BestOf / 2 + 0.5,0) AND player2Score=round(BestOf / 2 - 0.5,0))
) a
group by playerid
Select playerid,won, (Select SUM(won) from temp_score) as TotalPlayed from temp_score