【问题标题】: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=done 在state=done 的最后一个(即最近的)分组中的第一次出现。
【问题讨论】:
标签:
sql
postgresql
greatest-n-per-group
【解决方案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