Как мне суммировать только 3 лучших результата по этому запросу? - PullRequest
0 голосов
/ 29 апреля 2019

Мне нужно сложить только 5 лучших результатов для каждого игрока из 11 событий. Запрос ниже создает таблицу лидеров, которая суммирует все оценки, но я застрял в том, как я могу суммировать только 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 |
+--------+--------+--------+--------+--------+--------------+

Ответы [ 6 ]

2 голосов
/ 29 апреля 2019

Вот один из способов - хотя в 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 |
+--------+------+
2 голосов
/ 29 апреля 2019

Вы можете использовать коррелированный подзапрос, чтобы найти 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) суммируются.

Демонстрация на DB <> Fiddle

1 голос
/ 29 апреля 2019

Другой подход: 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 голосов
/ 29 апреля 2019

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 голосов
/ 29 апреля 2019

Использование 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 голосов
/ 29 апреля 2019

Я бы предложил использовать подзапрос в запросе, сгруппированном по concat (идентификатор игрока, идентификатор события), с ограничением 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);
...