代码之家  ›  专栏  ›  技术社区  ›  diplosaurus

mysql从多个列中计数出现次数

  •  4
  • diplosaurus  · 技术社区  · 8 年前

    games

    +---------+---------+---------+---------+---------+
    | 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    |
    +---------+---------+---------+---------+---------+
    

    mySQL query to find the most repeated value player1 最多但不是最多的玩家:

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

    +----+---------+--------+
    | id | game_id | player |
    +----+---------+--------+
    |  1 |    1001 | john   |
    |  2 |    1001 | dave   |
    |  3 |    1002 | john   |
    |  4 |    1002 | dave   |
    |  5 |    1002 | mike   |
    |  6 |    1002 | tim    |
    +----+---------+--------+
    
    2 回复  |  直到 8 年前
        1
  •  4
  •   revo shanwije    8 年前

    您最好的选择是规范化数据库。这是一个多对多关系,需要一个链接表来连接 运动员

    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

        2
  •  2
  •   M Khalid Junaid    8 年前

    我将从重新设计您的设计开始,介绍3个表

    CREATE TABLE players
        (`id` int, `name` varchar(255))
    ;
    INSERT INTO players
        (`id`,  `name`)
    VALUES
        (1, 'john'),
        (2, 'dave'),
        (3, 'mike'),
        (4, 'tim');
    

    CREATE TABLE games
        (`id` int, `name` varchar(25))
    ;
    
    INSERT INTO games
        (`id`, `name`)
    VALUES
        (1001, 'G1'),
        (1002, 'G2'),
        (1003, 'G3'),
        (1004, 'G4');
    

    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)
    ;
    

    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
    

    Demo

    哪对选手一起玩的最多?(约翰和戴夫)

    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;
    

    Demo