简体   繁体   中英

Highest for each group, with count

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

You should try something like this:

        select user_name, due_on, task_count, project_name
        from (
         SELECT
          users.name,
          projects.project_name,
          tasks.due_on,
          count(*) over (partition by user_name, project_name order by id desc) as AS task_count,
          row_number() over (partition by user_name, project_name order by id 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_at > '2012-01-01'
        ) t
        where rn = 1
        order by id;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM