Как рассчитать процентили для каждого уровня в игре, используя PostgreSQL 9.2 - PullRequest
2 голосов
/ 16 января 2020

У меня есть таблица игровых журналов. Например:


Level Shuffle_Count
  1        3
  2        1
  2        2
  2        1
  3        0
  3        4

Это означает, что всякий раз, когда пользователь играет на уровне, в таблицу добавляется строка. В этих строках есть данные об уровне, показывающие, какой уровень был воспроизведен пользователем, и данные shuffle_count, показывающие, сколько раз происходило случайное перемешивание на этом уровне.

Я хочу знать, сколько раз произошло случайное перемешивание на каждом уровне, вычислив медиану shuffle_count для каждого уровня. В приведенном ниже коде я могу найти медиану уровня 2 отдельно. Во-первых, я создаю временную таблицу, которая упорядочивает shuffle_counts, и делю их на 4 четные группы с помощью ntile. Затем я выбираю min shuffle_count, который имеет значение 3 в новом столбце с именем квартиль.

with ranked_test as (
    SELECT shuffle_count, ntile(4) OVER (ORDER BY shuffle_count) AS quartile FROM ch.public.game_log WHERE level = 2
)
SELECT min(shuffle_count) FROM ranked_test
WHERE quartile = 3
GROUP BY quartile;

Это таблица, созданная перед выбором min shuffle_count, где квартиль = 3 (медиана приблизительно):

Shuffle_Count quartile
     0           1
     0           1
     2           2
     3           2
     4           3
     8           3
     12          4
     19          4

Пока все хорошо. Но проблема в том, что у меня более 1000 уровней, и я не могу сделать это вручную для каждого уровня. Мне нужно медианное значение shuffle_count для каждого уровня от 1 до 1000. Я знаю, что это можно сделать с помощью одной строки в PostgreSQL 9.4, но, к сожалению, сейчас у меня нет этой опции.

Я не мог сделать это с помощью простой группы By. Я думаю, мне нужен более сложный запрос, включая FOR или что-то.

Есть идеи, ребята? Заранее спасибо.

1 Ответ

2 голосов
/ 16 января 2020

Я думаю, что это должно сделать это для вашего варианта использования:

with ranked_test as (
    select 
        level,
        shuffle_count, 
        ntile(4) over(partition by level order by shuffle_count) quartile 
    from ch.public.game_log
)
select level, quartile , min(shuffle_count) 
from ranked_test
where quartile = 3
group by level, quartile;

Это в основном расширенная версия вашего рабочего запроса:

  • в CTE мы удаляем фильтр на level в подзапросе и добавляем его к partition by оконной функции вместо

  • внешнего запроса, добавляем уровень к select и group by оговорка

...