简体   繁体   中英

MySQL query loads forever

I have a table with 1v1 matches like this:

match_number|winner_id|loser_id
------------+---------+--------
     1      |   1     |   2
     2      |   2     |   3
     3      |   1     |   2
     4      |   1     |   4
     5      |   4     |   1

and I would like to get something like this:

player|matches_won|matches_lost
------+-----------+------------
  1   |     3     |     1
  2   |     1     |     2
  3   |     0     |     1
  4   |     1     |     1

My MySQL Query looks like this

SELECT win_matches."winner_id" player, COUNT(win_matches."winner_id") matches_won, COUNT(lost_matches."loser_id") matches_lost FROM `matches` win_matches
JOIN `matches` lost_matches ON win_matches."winner_id" = lost_matches."winner_id"

I don't know what I did wrong, but the query just loads forever and doesn't return anything

You want to unpivot and then aggregate:

select player_id, sum(is_win), sum(is_loss)
from ((select winner_id as player_id 1 as is_win, 0 as is_loss
       from t
      ) union all
      (select loser_id, 0, 1
       from t
      ) 
     ) wl
group by player_id;

Your query is simply not correct. The two counts will produce the same same value -- COUNT(<expression>) returns the number of non- NULL rows for that expression. Your two counts return the same thing.

The reason it is taking forever is because of the Cartesian product problem. If a player has 10 wins and 10 losses, then your query produces 100 rows -- and this gets worse for players who have played more often. Processing all those additional rows takes time.

If you have a separate players table, then correlated subqueries may be the fastest method:

select p.*,
       (select count(*) from t where t.winner_id = p.player_id) as num_wins,
       (select count(*) from t where t.loser_id = p.player_id) as num_loses
from players p;

However, this requires two indexes for performance on (winner_id) and (loser_id) . Note these are separate indexes, not a single compound index.

You are joining the same table twice.

Both the alias win_matches and lost_matches are on the table matches , causing your loop.

You probably don't need separate tables for win and losses, and could do both in the same table by writing one or zero in a column for each.

I don't to change your model too much and make it difficult to understand, so here is a slight modification and what it could look like:

SELECT  m."player_id" player, 
    SUM(m."win") matches_won, 
    SUM(m."loss") matches_lost 
FROM `matches` m
GROUP BY player_id

Without a join, all in the same table with win and loss columns. It looked to me like you wanted to know the number of win and loss per player, which you can do with a group by player and a sum/count.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM