如何 select 与 table 中的项目相关的第一行和最后一行?

How to select the first and last row relevant to an item in a table?

我有以下 events table 跟踪与各种项目相关的事件:项目创建时间、更新时间以及最后删除时间。

例如它看起来像这样:

id item_id type
1 1 create
2 2 create
3 1 update
4 1 update
5 2 update
6 1 delete
7 2 update
8 3 create

所以在这个 table 中创建了项目 1,然后创建了项目 2,然后这两个项目被更新了多次。最后删除了item 1,但是item 2还在。最终项目 3 被创建并且从未被修改。

我正在尝试创建一个查询,为我提供每个项目的第一个和最后一个事件,所以在 运行 这个查询之后我会得到这个:

id item_id first_event_type last_event_type
1 1 create delete
2 2 create update
8 3 create NULL

我尝试了各种查询,但没有比加入 table 本身更进一步,因为我不知道如何表达加入的 table 应该 return 与当前相关的最后一个结果 item_id.

想知道是否可以只用一个查询来做到这一点?

(如果这能有所作为,我正在使用 PostgresSQL)

您可以使用 window 函数和条件聚合:

select item_id,
    max(type) filter(where rn_asc = 1) as first_event_type,
    max(type) filter(where rn_desc = 1 and rn_asc > 1) as last_event_type
from (
    select t.*,
        row_number() over(partition by item_id order by id) rn_asc,
        row_number() over(partition by item_id order by id desc) rn_desc
    from mytable t
) t
where 1 in (rn_asc, rn_desc)
group by item_id

Postgres 不支持“first”和“last”聚合函数。但是你可以接近 array_agg():

select item_id,
       (array_agg(type order by id))[1] as first_type,
       (array_agg(type order by id desc))[1] as last_type
from t
group by item_id;