每组最高,有计数

时间:2015-02-17 15:59:29

标签: sql postgresql group-by greatest-n-per-group

我使用PostgreSQL并拥有以下表格:

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

我想构建一个查询,为2012-01-01之后至少有一个任务到期的每个用户返回一行。它应列出用户名,用户的任务数,最远任务的日期以及与此最远任务相关联的项目名称。

使用上面的表格,结果应为

user_name max_due_on task_count project_name
joe       2015-02-18 2          p2
jack      2015-02-19 1          p1

我构建了以下查询,但它缺少与最远的到期任务相关联的项目名称。

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

有没有办法达到我的需要?

编辑:是工作查询,稍微改编自Bulat的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

1 个答案:

答案 0 :(得分:1)

你应该尝试这样的事情:

        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;