Pavel
Pavel

Reputation: 2101

Earliest timestamp with join before group

I have 3 tables users, levels, attempts in PostgreSQL. I need to select the earliest attempts by attempts.created_at for each user for each level and get sum of attempts.rate for each user.

CREATE TABLE IF NOT EXISTS users
(
    id       BIGSERIAL PRIMARY KEY,
    nickname VARCHAR(255) UNIQUE
);

CREATE TABLE IF NOT EXISTS levels
(
    id    BIGSERIAL PRIMARY KEY,
    title VARCHAR(255)   NOT NULL,
);

CREATE TABLE IF NOT EXISTS attempts
(
    id         BIGSERIAL PRIMARY KEY,
    rate       INTEGER NOT NULL,
    created_at TIMESTAMP NOT NULL,
    level_id   BIGINT REFERENCES levels (id),
    user_id    BIGINT REFERENCES users (id)
);

For example attempts content

id | rate | created_at                 | level_id | user_id
------------------------------------------------------------
1  | 10   | 2022-10-21 16:53:13.818000 | 1        | 1       
2  | 20   | 2022-10-21 11:53:13.818000 | 1        | 1       
3  | 30   | 2022-10-21 14:53:13.818000 | 1        | 1       
4  | 40   | 2022-10-21 10:53:13.818000 | 2        | 1          -- (nickname = 'Joe')
5  | 100  | 2022-11-21 10:53:13.818000 | 1        | 2          -- (nickname = 'Max') 

For level 1 and user 1 earliest row with id = 2 for level 2 with id = 4, I need select

nickname | sum
-----------------
Max      | 100
Joe      | 60

As a result for user Max (user with id = 1) sum of the earliest attempts of all levels = 100. And order by sum descending.

Something like this but how to select only one earliest attempt for each level before summing:

select u.nickname, sum(a.rate) as sum
from attempts a
         inner join users u on a.user_id = u.id
         inner join levels l on l.id = a.level_id
         -- on a.created_at is the earliest for level and user
group by u.id
order by sum desc

Upvotes: 0

Views: 36

Answers (1)

DannySlor
DannySlor

Reputation: 4620

select   user_id
        ,sum(rate)
from
(
select   distinct  on (level_id, user_id) *
from     t
order by level_id, user_id, created_at
) t
group by user_id
user_id sum
2 100
1 60

Fiddle

Upvotes: 1

Related Questions