I'm using PostgreSQL and have the following tables:
users id name 1 joe 2 jack
projects id name 1 p1 2 p2
tasks id name user_id project_id due_on 1 t1 1 1 2015-02-17 2 t2 1 2 2015-02-18 3 t3 2 1 2015-02-19
I want to build a query that returns a row for each user having at least one task due after 2012-01-01. It should list the user name, the number of tasks of the user, the date of the furthest out task, and the name of the project associated to this furthest out task.
With the tables above the result should be
user_name max_due_on task_count project_name joe 2015-02-18 2 p2 jack 2015-02-19 1 p1
I've build the following query but it is missing the name of project associated to the furthest out due task.
SELECT
users.name AS user_name,
max(tasks.due_on) AS max_due_on,
count(*) AS task_count
FROM tasks
LEFT JOIN users ON users.id = tasks.user_id
LEFT JOIN projects ON projects.id = tasks.project_id
WHERE
tasks.due_at > '2012-01-01'
GROUP BY users.name
Is there a way to achieve what I need?
EDIT: is is the working query, slightly adapted from Bulat's anwer:
SELECT user_name, due_at, task_count, project_name
from (
SELECT
users.name AS user_name,
projects.name AS project_name,
tasks.due_on,
count(*) OVER (PARTITION BY users.name) AS task_count,
row_number() over (PARTITION BY users.name ORDER BY tasks.due_on DESC) AS rn
FROM tasks
LEFT JOIN users ON users.id = tasks.user_id
LEFT JOIN projects ON projects.id = tasks.project_id
WHERE tasks.due_on > '2012-01-01'
) t
WHERE rn = 1
ORDER by user_name