[英]MySQL COUNT occurrences from several columns
I have the following table of matches of a 4 player game called games
. 我有一张名为games
的4人游戏的下表。
+---------+---------+---------+---------+---------+
| game_id | player1 | player2 | player3 | player4 |
+---------+---------+---------+---------+---------+
| 1001 | john | dave | NULL | NULL |
| 1002 | dave | john | mike | tim |
| 1003 | mike | john | dave | NULL |
| 1004 | tim | dave | NULL | NULL |
+---------+---------+---------+---------+---------+
There are two questions I want to be able to answer: 我希望能够回答两个问题:
For #1 I tried to adapt the answer I found here: mySQL query to find the most repeated value but it only seems to be able to answer the question for a single column. 对于#1我尝试调整我在这里找到的答案: mySQL查询找到最重复的值,但它似乎只能回答单个列的问题。 Meaning I could learn who was player1
the most, but not who played in the most games as any player: 意思是我可以了解谁是player1
,但不是任何玩家参加大多数游戏的人:
SELECT player1 p1, COUNT(*) p1 FROM games
GROUP BY p1
ORDER BY p1 DESC;
Is there a way to join these columns together or would I have to handle this in application code? 有没有办法将这些列连接在一起,还是我必须在应用程序代码中处理它?
Not sure where to start for #2. 不知道从哪里开始#2。 I'm wondering if my table structure should instead consolidate players to a single column: 我想知道我的表结构是否应该将玩家整合到一个列中:
+----+---------+--------+
| id | game_id | player |
+----+---------+--------+
| 1 | 1001 | john |
| 2 | 1001 | dave |
| 3 | 1002 | john |
| 4 | 1002 | dave |
| 5 | 1002 | mike |
| 6 | 1002 | tim |
+----+---------+--------+
Your best bet is normalizing database. 您最好的选择是规范化数据库。 This is a many-to-many relationship and needs a linked table to connect a game to its corresponding players . 这是一个多对多的关系,需要一个链接表来将游戏连接到相应的玩家 。 Then computations would be much more easier. 然后计算会更容易。 Nevertheless, you could use a derived table for question one that unites all columns into one: 尽管如此,您可以将派生表用于问题一,将所有列合并为一个:
SELECT `player`,
COUNT(*) as `count`
FROM
(
SELECT `player1` `player`
FROM `games`
UNION ALL
SELECT `player2` `player`
FROM `games`
UNION ALL
SELECT `player3` `player`
FROM `games`
UNION ALL
SELECT `player4` `player`
FROM `games`
) p
GROUP BY `player` HAVING `player` IS NOT NULL
ORDER BY `count` DESC
See live demo here 在这里查看现场演示
For the second question you have to have an inner join on derived table: 对于第二个问题,您必须在派生表上具有内部联接:
SELECT `p`.`player`,
`p2`.`player`,
count(*) AS count
FROM
(
SELECT `game_id`, `player1` `player`
FROM `games`
UNION ALL
SELECT `game_id`, `player2` `player`
FROM `games`
UNION ALL
SELECT `game_id`, `player3` `player`
FROM `games`
UNION ALL
SELECT `game_id`, `player4` `player`
FROM `games`
) p
INNER JOIN
(
SELECT `game_id`, `player1` `player`
FROM `games`
UNION ALL
SELECT `game_id`, `player2` `player`
FROM `games`
UNION ALL
SELECT `game_id`, `player3` `player`
FROM `games`
UNION ALL
SELECT `game_id`, `player4` `player`
FROM `games`
) p2
ON `p`.`game_id` = `p2`.`game_id` AND `p`.`player` < `p2`.`player`
WHERE `p`.`player` IS NOT NULL AND `p2`.`player` IS NOT NULL
GROUP BY `p`.`player`, `p2`.`player`
ORDER BY `count` DESC
See live demo here 在这里查看现场演示
I would start with restructuring your design and introduce 3 tables 我将从重构您的设计开始并介绍3个表
1) Player which will have player data and their unique ids 1)具有玩家数据及其唯一ID的玩家
CREATE TABLE players
(`id` int, `name` varchar(255))
;
INSERT INTO players
(`id`, `name`)
VALUES
(1, 'john'),
(2, 'dave'),
(3, 'mike'),
(4, 'tim');
2) Games which will have game data and their unique ids 2)具有游戏数据及其独特ID的游戏
CREATE TABLE games
(`id` int, `name` varchar(25))
;
INSERT INTO games
(`id`, `name`)
VALUES
(1001, 'G1'),
(1002, 'G2'),
(1003, 'G3'),
(1004, 'G4');
3) player_games to relate these 2 entities as many to many relationship via junction table which will hold game id and player id like as per your sample data 3)player_games通过联结表将这两个实体关联成多对多的关系,这将根据您的示例数据保存游戏ID和玩家ID
CREATE TABLE player_games
(`game_id` int, `player_id` int(11))
;
INSERT INTO player_games
(`game_id`, `player_id`)
VALUES
(1001, 1),
(1001, 2),
(1002, 1),
(1002, 2),
(1002, 3),
(1002, 4),
(1003, 3),
(1003, 1),
(1003, 2),
(1004, 4),
(1004, 2)
;
For Who played in the most games? 对于谁玩过大多数游戏? Its dave not john as per your sample data set who played 4 games 根据您玩4场比赛的样本数据集,它的dave不是约翰
select t.games_played,group_concat(t.name) players
from (
select p.name,
count(distinct pg.game_id) games_played
from player_games pg
join players p on p.id = pg.player_id
group by p.name
) t
group by games_played
order by games_played desc
limit 1
For above query there can be a chance that morethan one players have played most games like dave played 4 games and tim also played 4 games so both should be included 对于上面的查询,有可能超过一个玩家玩过大多数游戏,比如dave玩了4场比赛,蒂姆也打了4场比赛,所以两者都应该被包括在内
For What pair of players played the most games together? 对于哪一对队员一起玩过最多的比赛? (John & Dave) (约翰和戴夫)
select t.games_played,group_concat(t.player_name) players
from (
select group_concat(distinct pg.game_id),
concat(least(p.name, p1.name), ' ', greatest(p.name, p1.name)) player_name,
count(distinct pg.game_id) games_played
from player_games pg
join player_games pg1 on pg.game_id = pg1.game_id
and pg.player_id <> pg1.player_id
join players p on p.id = pg.player_id
join players p1 on p1.id = pg1.player_id
group by player_name
) t
group by games_played
order by games_played desc
limit 1;
In above query i have self joined player_games table to get the combination of players against each game and then grouped data for each unique pair , Again followed same logic to handel that there can be a chance that morethan one pair of players have played most games 在上面的查询中,我有自己加入的player_games表,以获得每个游戏的玩家组合,然后为每个唯一对分组数据,再次遵循相同的逻辑,汉德尔可能有超过一对玩家玩过大多数游戏的机会
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.