排除与Postgres中每个父记录相关的第一条记录

时间:2019-03-11 18:43:26

标签: sql postgresql offset

有2个表,usersjob_experiences

我想返回除与每个用户相关的第一个job_experiences之外的所有列表。

用户

id 
---
1
2
3

job_experiences

id | start_date | user_id
--------------------------
1  | 201001     | 1
2  | 201201     | 1
3  | 201506     | 1
4  | 200901     | 2
5  | 201005     | 2

所需结果

id | start_date | user_id
--------------------------
2  | 201201     | 1
3  | 201506     | 1
5  | 201005     | 2

当前查询

select 
   * 
from job_experiences
order by start_date asc
offset 1

但这不起作用,因为它需要将偏移量分别应用于每个用户。

3 个答案:

答案 0 :(得分:1)

使用row_number()窗口功能

with cte as
(
 select e.*,
 row_number()over(partition by user_id order by start_date desc) rn,
 count(*) over(partition by user_id) cnt
 from users u join job_experiences e on u.id=e.user_id
)
, cte2 as
(
 select * from cte 
) select * from cte2 t1
where rn<=(select max(cnt)-1 from cte2 t2 where t1.user_id=t2.user_id)

答案 1 :(得分:1)

您可以通过横向联接来做到这一点:

select je.*
from users u cross join lateral
     (select je.*
      from job_experiences je
      where u.id = je.user_id
      order by id
      offset 1  -- all except the first
     ) je;

为了提高性能,建议在job_experiences(user_id, id)上使用索引。

答案 2 :(得分:0)

您可以使用中间CTE为每个用户获取第一个(MIN)作业,然后使用该值确定要排除的记录:

WITH user_first_je("user_id", "job_id") AS
(
    SELECT "user_id", MIN("id")
    FROM job_experiences
    GROUP BY "user_id"
)
SELECT job_experiences.* 
FROM job_experiences
    LEFT JOIN user_first_je ON
        user_first_je.job_id = job_experiences.id
WHERE user_first_je.job_id IS NULL;