Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

250
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!