Creating a SQL query to sum and divide - mysql

I have this table:
Username | score | gameid
SimJoo | 14 | 1
SimJoo | 20 | 1
SimJoo | 23 | 2
Master | 32 | 1
Master | 25 | 2
Master | 9 | 2
For every player, I need the sum of the highest score of the player at every gameid divided by the highest score gotten for that gameid. This, for any number of different players, scores and gameids.
The result of above example table would be:
Username | total score
Master | 2.000
SimJoo | 1.545
For clarity:
The calculation for the player master is (32/32)+(25/25) =2.000
The calculation for the player SimJoo is (20/32)+(23/25) = 1.545
SELECT Username, SUM((SELECT MAX(score) WHERE Username=? AND gameid=?)/(SELECT MAX(Score) WHERE gameid=?)) AS total_score
GROUP BY Username
ORDER BY total_score DESC

The first subquery returns max score of user per game. The second one - max for games
select Username, sum(umax/gmax)
from
(select Username, gameid, max(score) umax
from t
group by Username, gameid
) u
left join
(select gameid, max(score) gmax
from t
group by gameid
) g
on u.gameid = g.gameid
group by Username
example on sqlfiddle

From what you describe, this requires two aggregations and a join:
select t.username, sum(t.score / g.maxscore)
from t join
(select gameid, max(score) as maxscore
from t
group by gameid
) g
on t.gameid = g.gameid
group by t.username;

Related

How to get ratio between the count of two columns grouped together in mysql (leaderboard kill/death ratio)

I've got a leaderboard in a pvp shooter game where I want to display the top 20 players ordered by their kill / death ratio (total kills divided by their total deaths)
I have a kills table that tracks kills and looks something like:
| killer_id | killed_id | date |
| patrick | jim | 2021-03-01 |
| greyson | jim | 2021-03-02|
| jim | patrick | 2021-03-03|
I can get the total kills by doing something like:
SELECT COUNT(*) as total_kills
FROM kills
GROUP BY killer_id
ORDER BY total_kills DESC
LIMIT 20
And I can get the total deaths by doing something like:
SELECT COUNT(*) as total_deaths
FROM kills
GROUP BY killed_id
ORDER BY total_deaths DESC
LIMIT 20
However, I can't seem to group the query together so that I'm returning a list of the best ratios. It would look like:
| player_id | kill_death_ratio (total kills / total deaths) |
| patrick | 2.1 |
| jim | 1.0 |
| greyson | .9 |
Is this even possible in a single query?
Use this query:
SELECT killer_id player_id FROM kills UNION SELECT killed_id FROM kills
to get all the players in the table.
Then join it with LEFT joins to your queries:
SELECT p.player_id,
COALESCE(t1.total_kills, 0) / t2.total_deaths kill_death_ratio
FROM (SELECT killer_id player_id FROM kills UNION SELECT killed_id FROM kills) p
LEFT JOIN (
SELECT killer_id, COUNT(*) total_kills
FROM kills
GROUP BY killer_id
) t1 ON t1.killer_id = p.player_id LEFT JOIN (
SELECT killed_id, COUNT(*) total_deaths
FROM kills
GROUP BY killed_id
) t2 ON t2.killed_id = p.player_id
Or, without your queries:
SELECT player_id, SUM(killer) / SUM(killed) kill_death_ratio
FROM (
SELECT killer_id player_id, 1 killer, 0 killed
FROM kills
UNION ALL
SELECT killed_id, 0, 1
FROM kills
) t
GROUP BY player_id
See the demo.
Results (for your sample data):
player_id
kill_death_ratio
jim
0.5
patrick
1.0
greyson
null
Notice that you will get null for players that were never killed.

Max() value from subquery with SUM() & multiple rows

I try to write a mysql query that display max value of a sub query but I don't. I have this primary query that works fine. This query select total points scored by each team for a specific game :
SELECT team_id, SUM(points) as totalpointsscored, game_id
FROM BOXSCORES
WHERE season="1920" and categorie=2
GROUP BY team_id, game_id
Output is like this :
team_id | value (points scored) | game_id
ASM | 98 | 9117338
ASM | 104 | 9117335
ASM | 75 | 9117324
LEM | 128 | 9117380
LEM | 97 | 9117316
STR | 95 | 9117334
STR | 102 | 9117177
STR | 88 | 9117469
I'd like to select now the max value for each team to know in what game a team scored the most. So, the output would be :
ASM | 104 | 9117335
LEM | 128 | 9117380
STR | 102 | 9117177
I try with group by and having but it doesn't work. team_id & value is ok but the game_id is always the first row & not the game_id attach to the value. Could you help me to find the best solution?
In MySQL 8.0, you can use window functions:
select *
from (
select
team_id,
sum(points) as total_points_scored,
game_id,
rank() over(partition by team_id order by sum(points) desc) rn
from boxscores
where season = '1920' and categorie = 2
group by team_id, game_id
) t
where rn = 1
In earlier versions, one solution is:
select
team_id,
sum(points) as total_points_scored,
game_id
from boxscores b
where season = '1920' and categorie = 2
group by team_id, game_id
having sum(points) = (
select sum(points)
from boxscore b1
where b1.season = b.season and b1.categorie = b.categorie and b1.team_id = b.team_id
group by game_id
order by sum(points) desc
limit 1
)
I fixed it.
I just add season & categorie in first query like this :
select
team_id,
sum(points) as total_points_scored,
game_id, season, categorie
from BOXSCORES b
where season= '1920' and categorie = 2
group by team_id, game_id
having sum(points) = (
select sum(points)
from BOXSCORES b1
where b1.season= b.season and b1.categorie = b.categorie and b1.team_id= b.team_id
group by game_id
order by sum(points) desc
limit 1
)

MySQL search value in two columns and sum third column

In my table "game_info" I have
ID | player_1 | player_2 | score
--------------------------------
1 | John | Rick | 100
2 | Joe | John | 80
3 | Bob | Rick | 210
I want to sum total score for every player no matter they are player_1 or player_2 and order by score.
What I expect is:
Name | Score
------------
Rick | 310
Bob | 210
John | 180
Joe | 80
I have tried to JOIN and UNION, but I can't get it right.
Is there any way to do this in sql or i have to redesign my table?
Thank You!
You can do this with union all and group by:
select player, sum(score)
from ((select player1 as player, score from game_info
) union all
(select player2 as player, score from game_info
)
) p
group by player
order by sum(score) desc;
SELECT player, SUM(score)
FROM
(SELECT player_1 AS player, score
FROM t
UNION ALL
SELECT player_2 as player, score
FROM t) sub
GROUP BY player
You have to union the player 1 results with the player 2 results, so that you have one result with just player and score. Of course, the scores will be listed twice in this view, one for each player. In my query, the result is called sub. Based on sub, you can group by player and sum their scores.

MySQL Ordering by win chance (%)

My table contains information this way:
Player_ID | isWinner
where PlayerID is the ID of the player, and isWinner is a boolean (0 for lose, 1 for win).
Same Player_ID can be in multiple rows.
My goal is to make a query to get ALL the information from this table ordered by the players, from the highest win rate (%) to the lowest.
Data example:
(Player_ID | isWinner)
1 | 1
1 | 1
1 | 1
2 | 0
2 | 0
2 | 1
3 | 0
3 | 0
3 | 0
The query will order this data this way:
1 | 100% -- > player ID 1 has the highest win rate
2 | 33% -- > player ID 2 has the 2nd win rate
3 | 0% -- > player ID 3 has the lowest win rate
I probably have to group by player_id and somehow calculate the SUM of isWinner of each player, then divide it by the numebr of records.
Any ideas?
You can use avg() to find the average of total wins for each player, then multiple by 100 to give the percentage
select
player_id as pid,
avg(is_winner) * 100 as win_rate,
(
SELECT
count(player_id)
FROM
`34617596`
WHERE
is_winner = 1
AND player_id = pid
) AS total_wins
FROM
`34617596`
group by pid
order by win_rate desc
See fiddle: http://sqlfiddle.com/#!9/10f797/1
This query will return the average for each player:
select player_id, avg(isWinner) as avg_is_winner
from players
group by player_id
then you can join your table with this subquery:
select players.*
from
players inner join (
select player_id, avg(isWinner) as avg_is_winner
from players
group by player_id
) c on players.player_id = c.player_id
order by
avg_is_winner desc,
isWinner desc
Please see a fiddle here.

Get Max value and corresponding column

How can I get corresponding columns from a max query in mysql? I want find out how many wins a player has. I will find that out by doing a count of the number of games that player has won. The will be done by selecting the max value per game and resulting player_id. However I am not sure how to get the corresponding player_id.
I have
id | game_id | player_id | score
1 | 1 | 1 | 254
2 | 1 | 2 | 194
3 | 2 | 1 | 432
4 | 2 | 2 | 298
This query should get what you need:
SELECT
player_id, game_id, score
FROM
(
SELECT game_id,MAX(score) AS MaxScore
FROM games
GROUP BY game_id
) AS Winners
JOIN games
ON (games.game_id = Winners.game_id AND games.score = Winners.MaxScore)
It assumes that a tie is a win for both players.
SQLFiddle
If you want to get just the player and their number of wins, you can use this query:
SELECT
player_id, COUNT(*) AS wins
FROM
(
SELECT game_id,MAX(score) AS MaxScore
FROM games
GROUP BY game_id
) AS Winners
JOIN games
ON (games.game_id = Winners.game_id AND games.score = Winners.MaxScore)
WHERE player_id = {player_id}
GROUP BY player_id
Just replace {player_id} with the player you're looking for and wins is their number of wins or ties.