如何仅将此查询中的3个最佳分数相加?

问题描述 投票:0回答:6

我需要将11个赛事中每个球员的5个最佳得分相加。下面的查询创建了一个排行榜,它总结了所有的分数,但我仍然坚持如何只能总结5个最佳分数。

我已经将查询缩写为仅显示4个事件并获得最佳3个结果以缩短帖子,但希望它能够实现,我需要什么。

SELECT playerID AS Player,
  SUM(CASE WHEN championshipleaderboard.eventID = 1 THEN championshipleaderboard.points ELSE 0 END) AS Event1,
  SUM(CASE WHEN championshipleaderboard.eventID = 2 THEN championshipleaderboard.points ELSE 0 END) AS Event2,
  SUM(CASE WHEN championshipleaderboard.eventID = 3 THEN championshipleaderboard.points ELSE 0 END) AS Event3,
  SUM(CASE WHEN championshipleaderboard.eventID = 4 THEN championshipleaderboard.points ELSE 0 END) AS Event4,
  SUM(championshipleaderboard.points) AS Total 
FROM (
  championshipleaderboard JOIN members ON championshipleaderboard.playerId = members.playerId
)
GROUP BY championshipleaderboard.playerId
ORDER BY Total DESC;

桌:锦标赛排行榜

+--------+---------+--------+
| Player | EventID | Points |
+--------+---------+--------+
|      1 |       1 |     25 |
|      2 |       1 |     20 |
|      1 |       2 |     15 |
|      2 |       2 |     13 |
|      1 |       3 |     20 |
|      2 |       3 |     12 |
|      1 |       4 |     20 |
|      2 |       4 |     10 |
+--------+---------+--------+

目前的结果是

+--------+--------+--------+--------+--------+-------+
| Player | Event1 | Event2 | Event3 | Event4 | Total |
+--------+--------+--------+--------+--------+-------+
|      1 |     25 |     15 |     20 |     20 |    80 |
|      2 |     20 |     13 |     12 |     10 |    55 |
+--------+--------+--------+--------+--------+-------+

需要的结果是

+--------+--------+--------+--------+--------+--------------+
| Player | Event1 | Event2 | Event3 | Event4 | Total(best3) |
+--------+--------+--------+--------+--------+--------------+
|      1 |     25 |     15 |     20 |     20 |           65 |
|      2 |     20 |     13 |     12 |     10 |           45 |
+--------+--------+--------+--------+--------+--------------+
mysql group-by aggregate-functions greatest-n-per-group mysql-5.7
6个回答
2
投票

您可以使用相关的子查询来查找第3个最佳分数,并将得分等于/大于第3个最佳分数:

SELECT Player
     , MIN(CASE WHEN Eventid = 1 THEN points END) AS Event1
     , MIN(CASE WHEN Eventid = 2 THEN points END) AS Event2
     , MIN(CASE WHEN Eventid = 3 THEN points END) AS Event3
     , MIN(CASE WHEN Eventid = 4 THEN points END) AS Event4
     , SUM(CASE WHEN (Points, ID) >= (
        SELECT Points, ID
        FROM t AS x
        WHERE x.Player = t.Player
        ORDER BY Points DESC, ID DESC
        LIMIT 2, 1
     ) THEN Points END) AS TopThree
FROM t
GROUP BY Player

请注意,排序点之间的关系可以通过Points DESC, ID DESC排序来打破;因此,如果球员的得分是(1, 20), (2, 20), (3, 30), (4, 30),那么(4, 30), (3, 30), (2, 20)总和。

Demo on DB<>Fiddle


2
投票

这是一种方式 - 虽然在MySQL 8+中,你会使用更现代的技术......

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(Player INT NOT NULL
,EventID INT NOT NULL
,Points INT NOT NULL
,PRIMARY KEY(player,eventid)
);

INSERT INTO my_table VALUES
(1,1,25),
(2,1,20),
(1,2,15),
(2,2,13),
(1,3,20),
(2,3,12),
(1,4,20),
(2,4,10);

SELECT player
     , SUM(points) top3 
  FROM 
     ( SELECT x.*
            , CASE WHEN @prev = player THEN @i:=@i+1 ELSE @i:=1 END i
            , @prev:=player 
         FROM my_table x
            , (SELECT @prev:=null,@i:=0) vars ORDER BY player,points
DESC) a 
        WHERE i<=3 
        GROUP 
           BY player;
+--------+------+
| player | top3 |
+--------+------+
|      1 |   65 |
|      2 |   45 |
+--------+------+

1
投票

另一种方法:https://www.db-fiddle.com/f/332F6XA3J3GaxXeD7LFP81/0

现场测试:

with ranking as
(
    select
        player,       
        rank() over(partition by player order by points desc) as xrank,
        points
    from tbl
)
select
    player, 
    sum(if(eventid = 1, points, 0)) as event1,
    sum(if(eventid = 2, points, 0)) as event2,
    sum(if(eventid = 3, points, 0)) as event3,  
    sum(if(eventid = 4, points, 0)) as event4,
    sum(
        if(
            (player,points) in
                (select player,points 
                from ranking 
                where xrank <= 3), 
            points, 
            0 
        ) 
    ) as best3
from tbl
group by player

输出:

| player | event1 | event2 | event3 | event4 | best3 |
| ------ | ------ | ------ | ------ | ------ | ----- |
| 1      | 25     | 15     | 20     | 20     | 65    |
| 2      | 20     | 13     | 12     | 10     | 45    |

0
投票

使用rank

现场测试:https://www.db-fiddle.com/f/4ufuFAXKf7mi5yefNQqoXM/2

with ranking as
(
   select 
      player,       
      rank() over(partition by player order by points desc) as xrank,
      points
  from tbl
)
,pick3 as
(
  select player, sum(points) as best3
  from ranking 
  where xrank <= 3
  group by player
)
select
   t.player, 
   sum(if(t.eventid = 1, t.points,0)) as event1,
   sum(if(t.eventid = 2, t.points,0)) as event2,
   sum(if(t.eventid = 3, t.points,0)) as event3,  
   sum(if(t.eventid = 4, t.points,0)) as event4,
   p.best3            
from tbl t
join pick3 p on t.player = p.player
group by t.player

输出:

| player | event1 | event2 | event3 | event4 | best3 |
| ------ | ------ | ------ | ------ | ------ | ----- |
| 1      | 25     | 15     | 20     | 20     | 65    |
| 2      | 20     | 13     | 12     | 10     | 45    |

0
投票

MySQL 5.7

现场测试:https://www.db-fiddle.com/f/4ufuFAXKf7mi5yefNQqoXM/15

select
    t.player, 
    sum(case when t.eventid = 1 then t.points end) as event1,
    sum(case when t.eventid = 2 then t.points end) as event2,
    sum(case when t.eventid = 3 then t.points end) as event3,
    sum(case when t.eventid = 4 then t.points end) as event4,

    sum(
        case when t.points >= (
            select best3.points 
            from tbl best3 
            where best3.player = t.player
            order by best3.points desc 
            limit 1 offset 2 -- offset starts with 0. so 2 is the third
        ) then 
            t.points
        end
    ) as best3            
from tbl t
group by t.player;

输出:

| player | event1 | event2 | event3 | event4 | best3 |
| ------ | ------ | ------ | ------ | ------ | ----- |
| 1      | 25     | 15     | 20     | 20     | 65    |
| 2      | 20     | 13     | 12     | 10     | 45    |

0
投票

我建议在由concat(玩家ID,事件ID)分组的查询中使用子查询,限制为3(或5,或多个)。

在我自己的数据库中的类似表上测试并工作。

编辑过的SQL:

SELECT cl.eventID, m.playerID,
   (SELECT 
        SUM(cl2.points)
    FROM
        championshipleaderboard cl2
    WHERE
        cl2.playerID = pr.playerID
            AND cl2.eventID = cl.eventID
    ORDER BY cl2.points DESC
    LIMIT 3) AS top_x_sum
 FROM championshipleaderboard cl, members m
   WHERE cl.playerID = m.playerID

 GROUP BY CONCAT(cl.eventID, m.playerID);
© www.soinside.com 2019 - 2024. All rights reserved.