简体   繁体   中英

MySQL query to count and score multiple columns

I have a MySQL table that looks like the following:

player_rankings | CREATE TABLE `player_rankings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `award_id` int(11) NOT NULL,
  `rank_1` int(11) DEFAULT NULL,
  `rank_2` int(11) DEFAULT NULL,
  `rank_3` int(11) DEFAULT NULL,
  `rank_4` int(11) DEFAULT NULL,
  `rank_5` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_id` (`user_id`,`award_id`)
) 

rank_1 through rank_5 contain ids of players that I have in a different table, but for the purpose of this query, it isn't relevant. What I am trying to do is count how many times a value shows up in each rank_* column and then give it the following amount of points:

  • rank_1 - 5 points
  • rank_2 - 4 points
  • rank_3 - 3 points
  • rank_4 - 2 points
  • rank_1 - 1 point

The end result would sort from highest to lowest (descending) the player ids with their total point count.

To get the sum of points per rank:

SELECT user_id,
  sum(rank1Points) rank1Points,
  sum(rank2Points) rank2Points,
  sum(rank3Points) rank3Points,
  sum(rank4Points) rank4Points,
  sum(rank5Points) rank5Points
FROM (
  SELECT pr.rank_1 user_id, count(*) * 5 rank1Points, 0 rank2Points, 0 rank3Points, 0 rank4Points, 0 rank5Points
  FROM player_rankings pr
  GROUP BY pr.rank_1
  UNION ALL
  SELECT pr.rank_2, 0, count(*) * 4, 0, 0, 0
  FROM player_rankings pr
  GROUP BY pr.rank_2
  UNION ALL
  SELECT pr.rank_3, 0, 0, count(*) * 3, 0, 0
  FROM player_rankings pr
  GROUP BY pr.rank_3
  UNION ALL
  SELECT pr.rank_4, 0, 0, 0, count(*) * 2, 0
  FROM player_rankings pr
  GROUP BY pr.rank_4
  UNION ALL
  SELECT pr.rank_5, 0, 0, 0, 0, count(*)
  FROM player_rankings pr
  GROUP BY pr.rank_5
) s
GROUP BY user_id

Fiddle here .

To get the total number of points together in one column:

SELECT user_id,
  sum(rankPoints) rankPoints
FROM (
  SELECT pr.rank_1 user_id, count(*) * 5 rankPoints
  FROM player_rankings pr
  GROUP BY pr.rank_1
  UNION ALL
  SELECT pr.rank_2, count(*) * 4
  FROM player_rankings pr
  GROUP BY pr.rank_2
  UNION ALL
  SELECT pr.rank_3, count(*) * 3
  FROM player_rankings pr
  GROUP BY pr.rank_3
  UNION ALL
  SELECT pr.rank_4, count(*) * 2
  FROM player_rankings pr
  GROUP BY pr.rank_4
  UNION ALL
  SELECT pr.rank_5, count(*)
  FROM player_rankings pr
  GROUP BY pr.rank_5
) s
GROUP BY user_id

Fiddle here .

For your table structure may be good solution is calculate all in script. Just get all rows and then calculate.

If you want make all in one SQL query then you can try use UNION for 5 subqueries

SELECT user_id, rank FROM(
   SELECT rank_1 AS user_id, 5 AS rank FROM player_rankings
   UNION
   SELECT rank_2 AS user_id, 4 AS rank FROM player_rankings
   ....
) AS u;

There is not working script, but I hope you understand my solution

Try

SELECT user_id, SUM(6 - rank) points
  FROM
(
  SELECT rank,
         CASE rank 
            WHEN 1 THEN rank_1
            WHEN 2 THEN rank_2
            WHEN 3 THEN rank_3
            WHEN 4 THEN rank_4
            WHEN 5 THEN rank_5
         END user_id
    FROM player_rankings t CROSS JOIN
  (
    SELECT 1 rank UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 4 UNION ALL
    SELECT 5 
  ) i
) q
 GROUP BY user_id
 ORDER BY points DESC

The idea behind this query is to first unpivot your table, then calculate points per user_id while grouping and then order the resultset descending by points. All in one query.

Sample output:

| USER_ID | POINTS |
|---------|--------|
|      50 |     13 |
|      10 |     12 |
|      30 |     12 |
|      20 |      9 |
|      40 |      5 |
|      60 |      4 |
|      70 |      3 |
|      80 |      2 |

Here is SQLFiddle demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM