获取计数行的最后一个实例

时间:2015-08-11 18:47:37

标签: sql postgresql date count greatest-n-per-group

有两个表jobsusersusersjobs的关系为1对多。

我想抓住已经完成5个或更多工作的所有用户的电子邮件。

下面的查询就是这样做的。但是,我如何还可以检索用户完成的上一个作业的日期。 所以期望的输出是:

Email          jobs done    date of last of job
jack@email.com   5+         1-20-2015  
joe@email.com    5+         2-20-2015

查询抓取已完成5个以上作业的用户的所有电子邮件

select
 email
 , case
 when times_used >= 5
  then '5+'
end as times_used
from
(
  select
  u.id
  , u.email as email
  , count(*) as times_used

from
  jobs j
  join users u on
    j.user_id = u.id
group by
  u.id
)
 a
  where
   times_used >= 5
   group by
    times_used
   , email

2 个答案:

答案 0 :(得分:1)

您可以为另一个派生表添加一个联接,该表拉取每个用户的最后日期:

select
    b.email, 
    case when times_used >= 5  then '5+' end as 'jobs done',
    b.max_date 'date of last job'
from (
    select u.id, count(*) as times_used
    from jobs j 
    join users u on j.user_id = u.id
    group by u.id
) a
join ( 
    select u.id, u.email, max(j.date) max_date 
    from jobs j
    join users u on j.user_id = u.id 
    group by u.id, email
) b on b.id = a.id 
where times_used >= 5

但是,如果您只想要有5个以上工作的所有用户的电子邮件,工作数量和上一个工作日期,那么下面的查询应该足够了:

select u.id, u.email, max(j.date) max_date 
from jobs j
join users u on j.user_id = u.id 
group by u.id, u.email
having count(j.id) >= 5

两个查询都假设jobs表格看起来像id (pk), user_id, date,因此您必须根据实际的表格定义进行调整。

答案 1 :(得分:0)

您应该尝试WINDOW函数方法,因为它可以更有效:

WITH user_jobs AS (
SELECT 
 u.id as user_id,
 j.id as job_id,
 u.email,
 ROW_NUMBER() OVER (PARTITION BY u.id ORDER BY j.date DESC) as rn,
 ROW_NUMBER() OVER (PARTITION BY u.id ORDER BY j.date) as job_number
FROM 
 jobs j
 join users u ON j.user_id = u.id
)
SELECT 
  user_id,
  job_id,
  email,
  job_number
FROM user_jobs
WHERE rn = 1 and job_number >= 5