我下面有一张这样的桌子。
ID Time State
1 1 "active"
1 2 "active"
1 3 "active"
1 4 "inactive"
2 2 "inactive"
2 3 "active"
3 1 "active"
3 3 "active"
3 4 "inactive"
我想按状态对开始/结束时间进行排序。
它可能需要lag()
窗口函数,但我不知道如何找到相同状态的终点。
我的期望表应如下所示。
ID Start End State
1 1 4 "active"
1 4 NULL "inactive"
2 2 3 "inactive"
2 3 NULL "active"
3 1 4 "active"
3 4 NULL "inactive"
答案 0 :(得分:1)
SELECT DISTINCT ON (sum) -- 5
id,
-- 4
first_value(time) OVER (PARTITION BY sum ORDER BY time) as start,
first_value(lead) OVER (PARTITION BY sum ORDER BY time DESC) as end,
state
FROM (
SELECT
*,
-- 3
SUM(CASE WHEN is_prev_state THEN 0 ELSE 1 END) OVER (ORDER BY id, time)
FROM (
SELECT
*,
-- 1
lead(time) OVER (PARTITION BY id ORDER BY time),
-- 2
state = lag(state) OVER (PARTITION BY id ORDER BY time) as is_prev_state
FROM states
)s
)s
lead()
将下一个值带到当前行。到time == 4
(id == 1
)转到带有time == 3
的行。这样做的目的是使组的最后一个位置排在右行。lag()
做相反的事情。它将前一个值作为当前行。这样,我可以检查状态是否已更改:当前状态是否与上一个相同?0
)。first_value()
完成的,该函数为您提供了有序组的第一个值。要获得最后一个值,您只需要按降序排列组即可。 (Why not using last_value()
)DISTINCT ON
仅过滤(使用SUM()
函数生成的)组的第一行