如何仅对该查询中的 3 个最佳分数求和?
How do I sum only the 3 best scores from this query?
我只需要对 11 场比赛中每位选手的 5 个最佳成绩求和。下面的查询创建了一个排行榜,它总结了所有的分数,但我对如何只能总结 5 个最好的分数感到困惑。
我已将查询缩写为仅显示 4 个事件并获得最佳 3 个结果以缩短 post,但希望它能理解我所需要的。
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;
table:冠军排行榜
+--------+---------+--------+
| 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 |
+--------+--------+--------+--------+--------+--------------+
您可以使用相关的子查询来找到第三个最好的分数,并且分数总和等于 to/greater 第三个最好的分数:
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)
相加。
我建议在按 concat(player ID, event 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);
使用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 |
另一种方法: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 |
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 |
这是一种方法 - 尽管在 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 |
+--------+------+
我只需要对 11 场比赛中每位选手的 5 个最佳成绩求和。下面的查询创建了一个排行榜,它总结了所有的分数,但我对如何只能总结 5 个最好的分数感到困惑。
我已将查询缩写为仅显示 4 个事件并获得最佳 3 个结果以缩短 post,但希望它能理解我所需要的。
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;
table:冠军排行榜
+--------+---------+--------+
| 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 |
+--------+--------+--------+--------+--------+--------------+
您可以使用相关的子查询来找到第三个最好的分数,并且分数总和等于 to/greater 第三个最好的分数:
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)
相加。
我建议在按 concat(player ID, event 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);
使用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 |
另一种方法: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 |
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 |
这是一种方法 - 尽管在 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 |
+--------+------+