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.
Related
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.
I've got a table like;
ID | Winner | Loser | WinningCaster | LosingCaster
0 | Player A | Player B | Warcaster A | Warcaster B
1 | Player A | Player B | Warcaster C | Warcaster A
2 | Player C | Player D | Warcaster A | Warcaster B
etc..
With various values for Player, and Warcaster.
WinningCaster / LosingCaster is a finite namelist, and I want to make a query that will find me which name occurs the most often, across both columns, both with and without a particular player entry.
IE Player A should return WarcasterA with 2, and an overall Query should return WarcasterA with 3.
So far I've only been able to get the most frequent from either column, not from both, with the following;
SELECT
ID, Winner, Loser, CasterWinner, Count(CasterWinner) AS Occ
FROM
`Games`
GROUP BY
CasterWinner
ORDER BY
Occ DESC
LIMIT 1
Use union all:
select caster, count(*)
from ((select casterwinner as caster from games
) union all
(select casterloser from games
)
) c
group by caster
order by count(*) desc
limit 1;
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.
I have a database of baseball plays with a PlayerID and a TypeID (the kind of play: double, strike out, etc). The data looks something like this:
+----------+--------+
| playerid | typeid |
+----------+--------+
| 2 | 4 |
| 2 | 4 |
| 2 | 7 |
| 3 | 7 |
| 3 | 7 |
| 3 | 7 |
| 3 | 26 |
| 3 | 7 |
I'm trying to find which players had the most of each kind of play. E.g. Jim (PlayerID 3) had the most strike outs (TypeID 7) and Bob (PlayerID 2) had the most home runs (TypeID 4) which should result in the following table:
+----------+--------+----------------+
| playerid | typeid | max(playcount) |
+----------+--------+----------------+
| 2 | 4 | 12 |
| 3 | 7 | 9 |
| 3 | 26 | 1 |
My best attempt so far is to run:
SELECT playerid,typeid,MAX(playcount) FROM
(
SELECT playerid,typeid,COUNT(*) playcount FROM plays GROUP BY playerid,typeid
) AS t GROUP BY typeid;
Which returns the proper maximums of each type, but the associated PlayerIDs are all wrong and I can't figure out why. I'm sure I'm missing something simple (or making this overly complicated) but can't figure it out. Any ideas?
In MySQL this group=wise maximum it is sadly not a simply as you want it to be.
Here's a way to do it using a method similar to what is suggested in ROW_NUMBER() in MySQL
SELECT a.*
FROM (
SELECT playerid
,typeid
,COUNT(*) playcount
FROM plays
GROUP BY playerid,typeid
) a
LEFT JOIN
(
SELECT playerid
,typeid
,COUNT(*) playcount
FROM plays
GROUP BY playerid,typeid
) b
ON a.typeid = b.typeid
AND a.playcount < b.playcount
WHERE b.playerid IS NULL
you have to put playerid column also in group by clause.
rest all is ok.
SELECT playerid,typeid,MAX(playcount) FROM
(
SELECT playerid,typeid,COUNT(*) playcount FROM plays GROUP BY playerid,typeid
) AS t GROUP BY playerid,typeid;
Would this work?
SELECT
playertypecounts.*
FROM
(SELECT
playerid,
typeid,
COUNT(*) as playcount
FROM plays
GROUP BY playerid, typeid) playertypecounts
INNER JOIN
(SELECT
typeid,
MAX(playcount) as maxplaycount
FROM
(SELECT
playerid,
typeid,
COUNT(*) as playcount
FROM plays
GROUP BY playerid, typeid) playcounts
GROUP BY typeid) maxplaycounts
ON playertypecounts.typeid = maxplaycounts.typeid
AND playertypecounts.playcount = maxplaycounts.maxplaycount
This part of the query block returns the maximum playcount for each typeid:
(SELECT
typeid,
MAX(playcount) as maxplaycount
FROM
(SELECT
playerid,
typeid,
COUNT(*) as playcount
FROM plays
GROUP BY playerid, typeid) playcounts
GROUP BY typeid) maxplaycounts
Then it's inner-joined to all the typeid/playcounts in order to filter those counts where the player(s) have the maximum counts for any given typeid.
See SQLFiddle example.
Having said all that, I actually prefer #KarlKieninger's answer since it's more elegant.
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.