Получить сумму верхних n-4 баллов за имя mySQL - PullRequest
0 голосов
/ 27 октября 2018

Как я могу получить сумму лучших n-4 очков за имя.Можем ли мы сделать это в одном операторе SQL без использования пользовательских переменных сеанса?

Входные данные: см. Ниже или Здесь (более ясное изображение)

Выходные данные: Смотрите ниже или Здесь (более четкое изображение)

Резюме:Джефф = 7 + 5 + 4 + 4 = 20Кат = 8 + 5 + 5 + 4 = 22Нил = 10 + 7 + 5 + 0 = 22Рик = 9 + 8 + 3 + 2 = 22

База данных ввода:± ± ----- ----------- ± ------- +|Имя |назначение |очки |± ± ----- ----------- ± ------- +|Джефф |1 |7 ||Джефф |2 |5 ||Джефф |3 |3 ||Джефф |4 |4 ||Джефф |5 |4 ||Кат |1 |4 ||Кат |2 |8 ||Кат |3 |5 ||Кат |4 |3 ||Кат |5 |5 ||Нил |1 |5 ||Нил |2 |7 ||Нил |3 |10 ||Нил |4 |0 ||Нил |5 |0 ||Рик |1 |2 ||Рик |2 |1 ||Рик |3 |8 ||Рик |4 |3 ||Рик |5 |9 |± ± ----- ----------- ± ------- +

Вывод: ± ----- ± ----------- ± ------- +|Имя |назначение |очки |± ± ----- ----------- ± ------- +|Джефф |20 ||Кат |22 ||Нил |22 ||Рик |22 |± ± ----- ----------- ± ------- +

Спасибо !!

1 Ответ

0 голосов
/ 28 октября 2018

Самое простое решение в MySQL 8+:

select name, sum(points)
from (select t.*, row_number() over (partition by name order by points desc) as seqnum
      from t
     ) t
where seqnum <= 4
group by name;

В более ранних версиях MySQL вам нужно было выполнять больше работы.Казалось бы, что-то вроде этого решит вашу проблему:

select t.name, sum(t.points)
from t
where t.assignment in (select t2.assignment
                       from t t2
                       where t2.name = t.name
                       order by t2.points desc
                       limit 4
                      )
group by t.name;

Но MySQL не поддерживает этот синтаксис.Если у вас не было дубликатов для точек, это сработало бы:

select t.name, sum(t.points)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points desc
                             limit 1 offset 3
                            ), 0)
group by t.name;

Но если 4-я и 5-я строки имеют одинаковые точки, то в сумме будет более 4 строк.

Теперь вы можете решить эту проблему с помощью переменных.,,но вместо этого мы можем адаптировать последнее решение:

select t.name,
       (case when count(*) = 4 then sum(t.points)
             else sum(t.points) - (count(*) - 4) * min(t.points)
        end)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points desc
                             limit 1 offset 3
                            ), 0)
group by t.name;

Это учитывает любые связи.Строго говоря, case не является необходимым, но я думаю, что это делает логику явной.

РЕДАКТИРОВАТЬ:

Если вы хотите все, кроме нижних четырех (ваш вопрос не ясен), тот же метод работает:

select t.name,
       (case when count(*) = 4 then sum(t.points)
             else sum(t.points) - (count(*) - 4) * min(t.points)
        end)
from t
where t.points >= coalesce( (select t2.points
                             from t t2
                             where t2.name = t.name
                             order by t2.points asc
                             limit 1 offset 3
                            ), 0)
group by t.name;

Единственная разница заключается в изменении порядка на.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...