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

Exclude first record associated with each parent record in Postgres

有 2 个表,usersjob_experiences

我想 return 列出所有 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

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

使用row_number()window函数

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)

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

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) 上建立索引。

您可以使用中间 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;