选择最后一组连续行中的第一行

Posted

技术标签:

【中文标题】选择最后一组连续行中的第一行【英文标题】:Select the first row in the last group of consecutive rows 【发布时间】:2021-08-17 03:07:25 【问题描述】:

如何选择连续行的最后一个“分组”中第一次出现的行,其中分组由特定列值的连续出现定义(在下面的示例中 state)。

例如,给定下表:

id datetime state value_needed
1 2021-04-01 09:42:41.319000 incomplete A
2 2021-04-04 09:42:41.319000 done B
3 2021-04-05 09:42:41.319000 incomplete C
4 2021-04-05 10:42:41.319000 incomplete C
5 2021-04-07 09:42:41.319000 done D
6 2021-04-012 09:42:41.319000 done E

我想要带有id=5 的行,因为它是state=donestate=done 的最后一个(即最近的)分组中的第一次出现。

【问题讨论】:

【参考方案1】:

假设所有列NOT NULL

SELECT *
FROM   tbl t1
WHERE  NOT EXISTS (
   SELECT FROM tbl t2
   WHERE  t2.state <> t1.state
   AND    t2.datetime > t1.datetime
   )
ORDER  BY datetime
LIMIT  1;

db小提琴here

NOT EXISTS 仅适用于最后一组对等点。 (没有后面的行具有不同的状态。) ORDER BY datetime 并拿下第一个。瞧。

【讨论】:

【参考方案2】:

这是一个窗口函数解决方案,它只访问您的表一次(对于大型数据集可能会或可能不会更好地执行):

SELECT *
FROM (
  SELECT *, 
    LEAD (state) OVER (ORDER BY datetime DESC) 
      IS DISTINCT FROM state AS first_in_group
  FROM tbl
) t
WHERE first_in_group
ORDER BY datetime DESC
LIMIT 1

基于Erwin Brandstetter's 的dbfiddle。为了说明,这里是每一行的first_in_group 的值:

id  datetime                 state       value_needed  first_in_group
---------------------------------------------------------------------
6   2021-04-12 09:42:41.319  done        E             f
5   2021-04-07 09:42:41.319  done        D             t
4   2021-04-05 10:42:41.319  incomplete  C             f
3   2021-04-05 09:42:41.319  incomplete  C             t
2   2021-04-04 09:42:41.319  done        B             t
1   2021-04-01 09:42:41.319  incomplete  A             t

【讨论】:

以上是关于选择最后一组连续行中的第一行的主要内容,如果未能解决你的问题,请参考以下文章

差距和岛屿 - 如何按 ID 对每组连续行求和

当两个或多个连续行具有相同状态时如何选择一行

有重复组时选择最后一组的第一条记录

Postgresql 选择最后一组的第一项

使用第一行和最后一行压缩多个连续行

excel如何快速选择第一行到最后一行