在我的Postgres 14数据库中,我有一个类似下面的表.

在我的SELECT中,我想添加两列来显示last_contract_idnext_contract_id,如果它们存在的话.棘手的部分是,如果rental_start_date在下面或上面的行上是相同的,我想跳过该行,直到它改变.所以在本例中,我希望807的last_contract_id为空,而不是806,因为第一行的id为3,rental_start_date发生了变化.

我试图添加这两行,但这并没有跳过具有相同rental_start_date的同行:

lag(contract_id) over (partition by objekt_id order by id) as last_contract_id, 
lead(contract_id) over (partition by objekt_id order by id) as next_contract_id 

Schema:

CREATE TABLE object_history (
    objekt_id int4 NOT NULL,
    id serial NOT NULL,
    rental_start date NULL,
    rental_end date NULL,
    contract_id int4 NULL
);

INSERT INTO public.object_history
(objekt_id, id, rental_start, rental_end, contract_id)
VALUES(77920, 6, '2023-06-01', '2100-01-01', 807);
INSERT INTO public.object_history
(objekt_id, id, rental_start, rental_end, contract_id)
VALUES(77920, 5, '2023-06-01', '2100-01-01', 806);
INSERT INTO public.object_history
(objekt_id, id, rental_start, rental_end, contract_id)
VALUES(77920, 4, '2023-06-01', '2100-01-01', 803);
INSERT INTO public.object_history
(objekt_id, id, rental_start, rental_end, contract_id)
VALUES(77920, 3, '2023-05-01', '2023-05-31', NULL);
INSERT INTO public.object_history
(objekt_id, id, rental_start, rental_end, contract_id)
VALUES(77920, 2, '2022-01-01', '2023-04-30', 802);
INSERT INTO public.object_history
(objekt_id, id, rental_start, rental_end, contract_id)
VALUES(77920, 1, '2017-11-01', '2021-12-31', NULL);
Select * from object_history;

| objekt_id | id  | rental_start             | rental_end               | contract_id |
| --------- | --- | ------------------------ | ------------------------ | ----------- |
| 77920     | 6   | 2023-06-01T00:00:00.000Z | 2100-01-01T00:00:00.000Z | 807         |
| 77920     | 5   | 2023-06-01T00:00:00.000Z | 2100-01-01T00:00:00.000Z | 806         |
| 77920     | 4   | 2023-06-01T00:00:00.000Z | 2100-01-01T00:00:00.000Z | 803         |
| 77920     | 3   | 2023-05-01T00:00:00.000Z | 2023-05-31T00:00:00.000Z |             |
| 77920     | 2   | 2022-01-01T00:00:00.000Z | 2023-04-30T00:00:00.000Z | 802         |
| 77920     | 1   | 2017-11-01T00:00:00.000Z | 2021-12-31T00:00:00.000Z |             |

View on DB Fiddle

推荐答案

使用窗口函数很难做到这一点.需要子查询...

以下是使用相关子查询而不是窗口函数的确切解决方案:

SELECT *
      , (SELECT contract_id FROM object_history o2 WHERE o2.objekt_id = o.objekt_id AND o2.rental_start IS DISTINCT FROM o.rental_start AND o2.id < o.id ORDER BY id DESC LIMIT 1) AS last_contract_id 
      , (SELECT contract_id FROM object_history o2 WHERE o2.objekt_id = o.objekt_id AND o2.rental_start IS DISTINCT FROM o.rental_start AND o2.id > o.id ORDER BY id      LIMIT 1) AS next_contract_id
FROM   object_history o
ORDER  BY objekt_id, rental_start, id

fiddle

不过,这并不算便宜.

Sql相关问答推荐

在postgresql中使用来自另一个字段的日期名称作为JSONB查询中的关键字

如何并行SELECT和RESET?

用于匹配红旗和绿旗的SQL查询

返回包含列和包含其他列的列表的自定义查询

SQL将 Select 查询作为新列添加到另一个 Select 查询

在SQL中使用类别值将行转置为列

没有循环的SQL更新多个XML node 值

使用Kotlin Exposed SQL DSL Select 多个值并排序

按分隔符和总和分析字符串

将日期时间转换为日期格式

使用SQL数据库中的现有列派生或修改几个列

聚合内部的条件在哪里?

YEAR 函数仍然不可SARGable 吗?

当我返回 sql 列时,有没有办法只反转数字? ( hebrew )

使用临时表判断记录是否存在 - 如果存在则执行相同的操作

在SQL中实现表格数据透视类型报表

SQL 多个不满足的条件失败

如何从一张表中获取值在至少三行相同的记录

MariaDB非常简单的MATCHAGAINST查询不使用FULLTEXT索引吗?

在Snowflake中如何使用SQL对版本字符串进行排序?