I've below tables players, matches.
player_id | group_id
-----------+----------
20 | 2
30 | 1
40 | 3
45 | 1
50 | 2
65 | 1
match_id | first_player | second_player | first_score | second_score
----------+--------------+---------------+-------------+--------------
1 | 30 | 45 | 10 | 12
2 | 20 | 50 | 5 | 5
13 | 65 | 45 | 10 | 10
5 | 30 | 65 | 3 | 15
42 | 45 | 65 | 8 | 4
Desired result:
group_id | winner_id
----------+-----------
1 | 45
2 | 20
3 | 40
Below are cases:
- In group 1 the winner is player 45 with the total score of 30 points.
- In group 2 both players scored 5 points, but player 20 has lower ID and is a winner.
- In group 3 there is only one player, and although she didn't play any matches, she is a winner.
I have written below query with left join & it satisfies all the 3 cases. But I need query without any join.
Below is query for reference:
select group_id,player_id,totalScores from
(select group_id,player_id,sum((
case when player_id = first_player then first_score
when player_id = second_player then second_score
end
)) as totalScores
from players p
left join matches m on (p.player_id = m.first_player or p.player_id = m.second_player)
group by group_id,player_id
order by group_id,totalScores desc,player_id ) as temp
group by group_id
order by group_id,totalScores desc,player_id
1条答案
按热度按时间twh00eeo1#
Your query is invalid. In the main query you group by group_id only, but select a player_id and totalScores. Which player_id? Which totalScores? There can be many per group_id. MySQL should raise an error here, and if it doesn't this indicaes that you are working in MySQL's notorious cheat mode that silently applies the
ANY_VALUE
function on such columns. Don't do that. You get arbitrarily chosen values that can even stem from different rows. In MySQL, alwaysin order not to be allowed to write invalid queries.
Apart from that, you have an
ORDER BY
clause in a subquery. A subquery cannot be ordered, and in fact, some DBMS would raise an error here. Subquery results are unordered sets of data by definition.If run in MySQL cheat mode, your query selects one row per group_id, each which an arbitrarily chosen player_id and and arbitrarily chosen total score. This is not what you want.
Here is a query that solves the task properly. It joins the tables as in your query, but then ranks the players by group_id with
ROW_NUMBER
. At last it shows the highest ranked player per group.(You could rank right away, but I thought it more readable to build the sums first and then rank in a separate step.)
As you say you don't want to join (which seems a very weird request) and you only need the players' total scores from the matches table, you can replace the outer join by a subquery in the players' select clause:
Demo: https://dbfiddle.uk/PxP_gMXI