我在您的原始表中发现了一些重复项,例如 Ross 和 Chandler 有 2 个条目具有完全相同的数据集。如果那是复制/粘贴错误,那么我复制了您的案例:
create table testdt(name varchar, hire_dt date, eff_dt date);
insert into testdt values('Rachel','2021-03-29','2021-03-29');
insert into testdt values('Rachel','2021-03-29','2021-05-14');
insert into testdt values('Ross','2021-06-18','2021-06-18');
insert into testdt values('Monica','2021-07-21','2021-07-21');
insert into testdt values('Chandler','2021-04-12','2021-04-12');
insert into testdt values('Judy','2021-04-26','2021-04-26');
insert into testdt values('Judy','2021-04-26','2021-05-10');
insert into testdt values('Judy','2021-04-26','2021-07-01');
现在,正如您的标签所提到的那样,您需要使用 LAG 和 LEAD 函数,这将相应地从上一行和下一行获取列。
如果您在上述testdt 表上运行以下SQL,您将获得上一个和下一个eff_dt。请注意我使用ctid 作为排序列
select *,
ctid,
lead(eff_dt) over (partition by name order by ctid) as lead_eff_dt,
lag(eff_dt) over (partition by name order by ctid) as lag_eff_dt
from testdt tst order by ctid
结果如下
name | hire_dt | eff_dt | ctid | lead_eff_dt | lag_eff_dt
----------+------------+------------+-------+-------------+------------
Rachel | 2021-03-29 | 2021-03-29 | (0,1) | 2021-05-14 |
Rachel | 2021-03-29 | 2021-05-14 | (0,2) | | 2021-03-29
Ross | 2021-06-18 | 2021-06-18 | (0,3) | |
Monica | 2021-07-21 | 2021-07-21 | (0,4) | |
Chandler | 2021-04-12 | 2021-04-12 | (0,5) | |
Judy | 2021-04-26 | 2021-04-26 | (0,6) | 2021-05-10 |
Judy | 2021-04-26 | 2021-05-10 | (0,7) | 2021-07-01 | 2021-04-26
Judy | 2021-04-26 | 2021-07-01 | (0,8) | | 2021-05-10
现在我们可以应用您的逻辑:
START_DATE
如果是第一行(lag_eff_dt 是null),那么我们使用hire_dt,否则,如果有下一行(lead_eff_dt 不是null),那么我们使用以下eff_dt。如果是最后一行,我们取eff_dt。
END_DATE
如果没有后续记录(lead_eff_dt 是null)我们只需要取2021-12-31,否则我们从下一个eff_dt 休息一天
下面的查询应该做
with first_sel as(
select *,
ctid,
lead(eff_dt) over (partition by name order by ctid) as lead_eff_dt,
lag(eff_dt) over (partition by name order by ctid) as lag_eff_dt
from testdt tst order by ctid)
select
name,
case when lag_eff_dt is null
then hire_dt
else
case when lead_eff_dt is not null
then (lead_eff_dt)::date
else eff_dt
end
end as start,
coalesce((lead_eff_dt - INTERVAL '1 DAY')::date, '2021-12-31'::date) as end
from first_sel;
结果是
name | start | end
----------+------------+------------
Rachel | 2021-03-29 | 2021-05-13
Rachel | 2021-05-14 | 2021-12-31
Ross | 2021-06-18 | 2021-12-31
Monica | 2021-07-21 | 2021-12-31
Chandler | 2021-04-12 | 2021-12-31
Judy | 2021-04-26 | 2021-05-09
Judy | 2021-07-01 | 2021-06-30
Judy | 2021-07-01 | 2021-12-31
(8 rows)