MySQL查询永远加载

时间:2019-12-22 12:29:58

标签: mysql sql query-performance

我有一个具有1v1匹配的表格,如下所示:

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

我想得到这样的东西:

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

我的MySQL查询看起来像这样

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"

我不知道我做错了什么,但是查询将永远加载并且不返回任何内容

2 个答案:

答案 0 :(得分:0)

您要先取消透视然后汇总:

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;

您的查询根本不正确。这两个计数将产生相同的值-COUNT(<expression>)返回该表达式的非NULL行的数量。您的两个伯爵返回同一件事。

之所以要永久使用是因为笛卡尔积问题。如果一个玩家有10赢10输,那么您的查询会产生100行-对于玩得更多的玩家来说,情况会变得更糟。处理所有其他行需要花费时间。

如果您有单独的players表,则关联子查询可能是最快的方法:

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;

但是,这需要两个索引来提高(winner_id)(loser_id)的性能。请注意,这些是单独的索引,而不是单个复合索引。

答案 1 :(得分:0)

您两次连接同一张桌子。

别名win_matcheslost_matches都在表matches上,从而导致循环。

您可能不需要单独的表格来表示获胜和失败,并且可以通过在每个表格的一列中写入一个或零来在同一个表格中完成这两个操作。

我不会对您的模型进行太多更改,以至于难以理解,因此这里做了一些微小的修改,其外观可能是这样的:

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

如果没有联接,则所有表都在同一表中,其中包含获胜和损失列。在我看来,您似乎想知道每位玩家的获胜和失败次数,您可以按玩家分组以及总和/次数来完成。