MySQL 查询永远加载
MySQL query loads forever
我有一个 table 的 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"
我不知道我做错了什么,但查询只是永远加载并且 return 没有任何内容
您想先逆轴再聚合:
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>)
returns 该表达式的非 NULL
行数。你的两个计数 return 是一样的。
一直拖延的原因是笛卡尔积问题。如果一个玩家赢了 10 场,输了 10 场,那么您的查询会产生 100 行——对于玩得更频繁的玩家来说,情况会更糟。处理所有这些额外的行需要时间。
如果你有单独的players
table,那么关联子查询可能是最快的方法:
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)
的性能。请注意,这些是单独的索引,而不是单个复合索引。
您将加入同一个 table 两次。
别名 win_matches
和 lost_matches
都在 table matches
上,导致循环。
您可能不需要单独的 table 来表示输赢,并且可以在相同的 table 中通过在每列中写一个或零来实现。
我不想对你的模型做太多改变,让它难以理解,所以这里稍微修改一下,它看起来像:
SELECT m."player_id" player,
SUM(m."win") matches_won,
SUM(m."loss") matches_lost
FROM `matches` m
GROUP BY player_id
没有连接,全部在同一个 table 中,有输赢列。在我看来,您想知道每个玩家的输赢次数,这可以通过玩家分组和 sum/count.
来实现
我有一个 table 的 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"
我不知道我做错了什么,但查询只是永远加载并且 return 没有任何内容
您想先逆轴再聚合:
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>)
returns 该表达式的非 NULL
行数。你的两个计数 return 是一样的。
一直拖延的原因是笛卡尔积问题。如果一个玩家赢了 10 场,输了 10 场,那么您的查询会产生 100 行——对于玩得更频繁的玩家来说,情况会更糟。处理所有这些额外的行需要时间。
如果你有单独的players
table,那么关联子查询可能是最快的方法:
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)
的性能。请注意,这些是单独的索引,而不是单个复合索引。
您将加入同一个 table 两次。
别名 win_matches
和 lost_matches
都在 table matches
上,导致循环。
您可能不需要单独的 table 来表示输赢,并且可以在相同的 table 中通过在每列中写一个或零来实现。
我不想对你的模型做太多改变,让它难以理解,所以这里稍微修改一下,它看起来像:
SELECT m."player_id" player,
SUM(m."win") matches_won,
SUM(m."loss") matches_lost
FROM `matches` m
GROUP BY player_id
没有连接,全部在同一个 table 中,有输赢列。在我看来,您想知道每个玩家的输赢次数,这可以通过玩家分组和 sum/count.
来实现