MySQL查询将永远加载

问题描述 投票:0回答:2

我有一个具有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"

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

mysql sql query-performance
2个回答
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)的性能。请注意,这些是单独的索引,而不是单个复合索引。


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

[没有联接,所有变量都在同一表中,其中包含获胜和损失列。在我看来,您似乎想知道每位玩家的获胜和失败数量,您可以按玩家分组并进行总和/计数。

© www.soinside.com 2019 - 2024. All rights reserved.