来自多个列的 MySQL COUNT 次出现

标签 mysql

我有一个名为 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    |
+---------+---------+---------+---------+---------+

我想回答两个问题:

  1. 谁参加的比赛最多? (戴夫)
  2. 哪对球员一起打的比赛最多? (约翰和戴夫)

对于 #1,我尝试调整我在这里找到的答案:mySQL query to find the most repeated value但它似乎只能回答一个专栏的问题。这意味着我可以了解谁是 player1 最多的人,但不是任何玩家中玩游戏次数最多的人:

SELECT player1 p1, COUNT(*) p1 FROM games
GROUP BY p1    
ORDER BY p1 DESC;

有没有办法将这些列连接在一起,或者我必须在应用程序代码中处理吗?

不确定#2 从哪里开始。我想知道我的表结构是否应该将玩家合并到一个列中:

+----+---------+--------+
| id | game_id | player |
+----+---------+--------+
|  1 |    1001 | john   |
|  2 |    1001 | dave   |
|  3 |    1002 | john   |
|  4 |    1002 | dave   |
|  5 |    1002 | mike   |
|  6 |    1002 | tim    |
+----+---------+--------+

最佳答案

最好的办法是规范化数据库。这是一个多对多的关系,需要一个链接表来将一个游戏连接到它对应的玩家。那么计算就会容易得多。不过,您可以为第一个问题使用派生表,将所有列合并为一个:

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

参见 live demo here

对于第二个问题,您必须在派生表上进行内部联接:

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

参见 live demo here

关于来自多个列的 MySQL COUNT 次出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50866776/

相关文章:

将 1 个字段复杂地移动到另一个数据库中的字段中需要 mysql 查询

mysql - 从一张 MySQL 表中选择一份 Diff 报告

mysql - 我什么时候应该使用 mongoDB 而不是关系数据库

php - 在没有 PDO::PARAM 的情况下绑定(bind)参数是否安全?

MYSQL 使用四个 INNER JOINS 更新表

php - 如何将照片上传到数据库中,只需将文件名保存为 VARCHAR?

mysql - Perl:用一次 MySQL 调用更新多行

MySQL:为 `show tables` 声明游标?

mysql - 使用 GROUP_CONCAT 重复值而不在具有多个连接的 MySQL 查询上使用 DISTINCT

python - 使用 Python 将一个 .csv 中的列添加到另一个 .csv 文件