This is my table:
+--------+-------+--------+--------+
| player | points| score1 | score2 |
+--------+-------+--------+--------+
| 1 | 12 | 9 | 1 |
| 2 | 12 | 14 | 2 |
| 3 | 10 | 12 | 3 |
| 4 | 9 | 10 | 4 |
| 5 | 8 | 10 | 4 |
+--------+-------+--------+--------+
To get the second highest value, I used this query:
SELECT player,points FROM players
WHERE points= (SELECT DISTINCT(points) FROM players as p1
WHERE (SELECT COUNT(DISTINCT(points))=2 FROM players as p2
WHERE p1.points<= p2.points)) ORDER BY player
It works perfect. But now I want to get is with two conditions:
Condition1: points DESC
Condition2: (score1-score2) DESC
This query works fine to get the player with the second highest value (Checking points and score1):
SELECT player,points FROM players
WHERE points= (SELECT DISTINCT(points) FROM players as p1
WHERE (SELECT COUNT(DISTINCT(points))=2 FROM players as p2
WHERE p1.points<= p2.points))
AND
WHERE score1= (SELECT DISTINCT(score1) FROM players as p1
WHERE (SELECT COUNT(DISTINCT(score1))=2 FROM players as p2
WHERE p1.score1<= p2.score1))
ORDER BY player
How can I get the player with the second highest value using two conditions (points DESC AND (score1-score2) DESC)?
This query will do what you want. It JOINs players to itself, looking for all players in the second table who would rank higher than the player in the first table. In this case ranking is based first on points, then in case of equal points on the difference between score1 and score2. The second ranked player is the one who has one player with higher rank than they do:
SELECT p1.*
FROM players p1
JOIN players p2 ON p2.points > p1.points
OR p2.points = p1.points AND (p2.score1 - p2.score2) > (p1.score1 - p1.score2)
GROUP BY p1.player
HAVING COUNT(p2.player) = 1
Output:
player points score1 score2
1 12 9 1
You can also write your original query in a similar fashion, using p2.player < p1.player as a condition to separate players with equal points (simulating the effect of your ORDER BY player):
SELECT p1.*
FROM players p1
JOIN players p2 ON p2.points > p1.points
OR p2.points = p1.points AND p2.player < p1.player
GROUP BY p1.player
HAVING COUNT(p2.player) = 1
Output:
player points score1 score2
2 12 14 2
Demo on dbfiddle
Related
I have 2 tables, players and stats.
Table players have an id and a name, while the table stats looks like this:
id | Player | Stat | Value
1 | 0000001 | Wins | 5
2 | 0000001 | Loses | 6
3 | 0000001 | Jumps | 156
4 | 0000001 | Shots | 580
5 | 0000002 | Wins | 15
6 | 0000002 | Loses | 2
7 | 0000002 | Jumps | 530
8 | 0000002 | Shots | 1704
I want to filter players that match several conditions, like, for example, players that have more than 5 wins but less than 200 jumps.
I tried this
SELECT players.name
FROM players
LEFT JOIN stats
ON stats.player = players.id
WHERE (stats.stat = "Wins" AND stats.value > 5)
AND (stats.stat = "Jumps" AND stats.value < 200)
GROUP BY players.id
But it returns nothing, because the GROUP BY goes after the WHERE.
I also tried using OR.
SELECT players.name
FROM players
LEFT JOIN stats
ON stats.player = players.id
WHERE (stats.stat = "Wins" AND stats.value > 5)
OR (stats.stat = "Jumps" AND stats.value < 200)
GROUP BY players.id
But in that case, it returns the players that match any of the conditions, and I only want the ones that match both conditions. In this specific example, it should only return the player with id 0000001.
I know I could do it with a different LEFT JOIN for every different stat, but truth is the actual table is huge and has tons of diferent stats, so I don't think that is an option because it would be very slow.
There is no need to aggregate. You can do this with two inner joins, one per condition:
SELECT p.name
FROM player p
INNER JOIN stats s1 ON s1.player = p.id AND s1.stat = 'Wins' AND s1.value > 5
INNER JOIN stats s2 ON s2.player = p.id AND s2.stat = 'Jumps' AND s2.value < 200
With an index on stats(player, stat, value), this should be an efficient option.
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.
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.
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.