Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

252
Visualizações
Top N values in window frame

I have a table t with 3 fields of interest: d (date), pid (int), and score (numeric)

I am trying to calculate a 4th field that is an average of each player's top N (3 or 5) scores for the days before the current row.

I tried the following join on a subquery but it is not producing the results I'm looking for:

SELECT t.d, t.pid, t.score, sq.highscores 
FROM t, (SELECT *, avg(score) as highscores FROM
   (SELECT *, row_number() OVER w AS rnum
    FROM t AS t2
    WINDOW w AS (PARTITION BY pid ORDER BY score DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)) isq
    WHERE rnum <= 3) sq
WHERE t.d = sq.d AND t.pid = sq.pid

Any suggestions would be greatly appreciated! I'm a hobbyist programmer and this is more complex of a query than I'm used to.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

You can't select * and avg(score) in the same (inner) query. I.e. which non-aggregated values should be selected for each average? PostgreSQL won't decide this instead of you.

Becasue you PARTITION BY pid in the innermost query, you should use GROUP BY pid in the aggregating subquery. That way, you can SELECT pid, avg(score) as highscores:

SELECT   pid, avg(score) as highscores
FROM     (SELECT *, row_number() OVER w AS rnum
          FROM t AS t2
          WINDOW w AS (PARTITION BY pid ORDER BY score DESC)) isq
WHERE    rnum <= 3
GROUP BY pid

Note: ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING makes no difference for row_number().

But if the top N part is fixed (and N will be few in your real-world use-case too), you can solve this without that much subquery (with the nth_value() window function):

SELECT d, pid, score,
       (coalesce(nth_value(score, 1) OVER w, 0) +
        coalesce(nth_value(score, 2) OVER w, 0) +
        coalesce(nth_value(score, 3) OVER w, 0)) /
       ((nth_value(score, 1) OVER w IS NOT NULL)::int +
        (nth_value(score, 2) OVER w IS NOT NULL)::int +
        (nth_value(score, 3) OVER w IS NOT NULL)::int) highscores
FROM   t
WINDOW w AS (PARTITION BY pid ORDER BY score DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)

http://rextester.com/GUUPO5148

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda