我有下表:
+----------+------------------------+-----------+---------------------+
| PersonId | Role | TeamId | EffectiveDate |
+----------+------------------------+-----------+---------------------+
| 0001813 | admin | 005aba1ec | 2019-05-01 00:00:00 |
| 0001813 | scrum master | 005aba1ec | 2019-05-01 00:00:00 |
| 0001813 | team captain | 005aba1ec | 2019-05-01 00:00:00 |
| 0001813 | admin | 005aba1ec | 2019-06-01 00:00:00 |
| 0001813 | scrum master | 005aba1ec | 2019-06-01 00:00:00 |
| 0001813 | team captain | 005aba1ec | 2019-06-01 00:00:00 |
| 0001813 | delivery lead | 005aba1ec | 2019-06-01 00:00:00 |
| 0002817 | product lead | 007aba338 | 2019-07-01 00:00:00 |
| 0002817 | finance partner | 007aba338 | 2019-07-01 00:00:00 |
| 0002817 | individual contributor | 007aba338 | 2019-07-01 00:00:00 |
| 0002817 | product lead | 007aba338 | 2019-08-01 00:00:00 |
| 0002817 | finance partner | 007aba338 | 2019-08-01 00:00:00 |
| 0002817 | individual contributor | 007aba338 | 2019-08-01 00:00:00 |
| 0002817 | admin | 007aba338 | 2019-08-01 00:00:00 |
+----------+------------------------+-----------+---------------------+
我想获得每行的下一个生效日期。对于具有相同生效日期的行,我想获取下一个更大的生效日期。本质上,我想获得以下结果:
+----------+------------------------+-----------+---------------------+---------------------+
| PersonId | Role | TeamId | EffectiveDate | NextEffectiveDate |
+----------+------------------------+-----------+---------------------+---------------------+
| 0001813 | admin | 005aba1ec | 2019-05-01 00:00:00 | 2019-06-01 00:00:00 |
| 0001813 | scrum master | 005aba1ec | 2019-05-01 00:00:00 | 2019-06-01 00:00:00 |
| 0001813 | team captain | 005aba1ec | 2019-05-01 00:00:00 | 2019-06-01 00:00:00 |
| 0001813 | admin | 005aba1ec | 2019-06-01 00:00:00 | 9999-12-31 23:59:59 |
| 0001813 | scrum master | 005aba1ec | 2019-06-01 00:00:00 | 9999-12-31 23:59:59 |
| 0001813 | team captain | 005aba1ec | 2019-06-01 00:00:00 | 9999-12-31 23:59:59 |
| 0001813 | delivery lead | 005aba1ec | 2019-06-01 00:00:00 | 9999-12-31 23:59:59 |
| 0002817 | product lead | 007aba338 | 2019-07-01 00:00:00 | 2019-08-01 00:00:00 |
| 0002817 | finance partner | 007aba338 | 2019-07-01 00:00:00 | 2019-08-01 00:00:00 |
| 0002817 | individual contributor | 007aba338 | 2019-07-01 00:00:00 | 2019-08-01 00:00:00 |
| 0002817 | product lead | 007aba338 | 2019-08-01 00:00:00 | 9999-12-31 23:59:59 |
| 0002817 | finance partner | 007aba338 | 2019-08-01 00:00:00 | 9999-12-31 23:59:59 |
| 0002817 | individual contributor | 007aba338 | 2019-08-01 00:00:00 | 9999-12-31 23:59:59 |
| 0002817 | admin | 007aba338 | 2019-08-01 00:00:00 | 9999-12-31 23:59:59 |
+----------+------------------------+-----------+---------------------+---------------------+
我尝试在Postgres中使用LEAD
函数,但我不认为PARTITION BY
的工作方式与我认为的相同:
LEAD(EffectiveDate) OVER (PARTITION BY EffectiveDate ORDER BY EffectiveDate) AS NextEffectiveDate
关于如何实现这一目标的任何想法?预先感谢。
答案 0 :(得分:1)
SELECT
*,
COALESCE (
MAX("EffectiveDate") OVER
(PARTITION BY "PersonId" ORDER BY "EffectiveDate" GROUPS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
,
'9999-12-31 23:59:59'
)
FROM mytable
PostgreSQL 11 在窗口函数中添加了对GROUPS
的支持。这正是它的目的。您希望始终获得EffectiveDate
组的值。可以将其与PersonId
分区结合使用,因为您只希望每个人都拥有GROUPS
功能。 Further reading
然后,COALESCE()
函数将最后一个GROUPS
结果的NULL值重置为默认值。
答案 1 :(得分:1)
从Postgres 11开始,您还可以使用range
定义的窗口函数来完成此操作:
MIN(EffectiveDate) OVER
(PARTITION BY PersonId
ORDER BY EffectiveDate
RANGE BETWEEN INTERVAL '1 SECOND' FOLLOWING AND UNBOUNDED FOLLOWING
) AS NextEffectiveDate
在早期版本中,您可以使用两级窗口功能:
select t.*,
nullif(max(next_id) over (partition by personid, effectivedate), effectivedate) as next_effectivedate
from (select t.*,
lead(effectivedate) over (partition by personid order by effectivedate) as next_ed
from t
) t