【问题标题】:How to find end point of same value with interval?如何找到具有间隔的相同值的端点?
【发布时间】:2018-12-19 15:20:45
【问题描述】:

我有一张像下面这样的表格。

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"  

【问题讨论】:

  • 在您的预期输出中,您写了 Start = 1, End = 4 表示状态不活动。您是说 Start = 4 吗?
  • 嗨,S-Man,感谢您指出这一点。我纠正了它:)

标签: postgresql


【解决方案1】:

demo:db<>fiddle

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
  1. lead() 将下一个值带到当前行。例如time == 4 (id == 1) 与time == 3 一起进入行。这个想法是让一个可能的组结束到正确的行。
  2. lag() 做相反的事情。它采用当前行的前一个值。有了它,我可以检查一个状态是否发生了变化:当前状态是否与上一个状态相同。
  3. 通过这一行,我为每个单独的状态创建了组:如果状态发生了变化,总结一个值。如果不保持相同的值(添加0)。
  4. 现在我有了每个状态可能的最后一个值(通过 (1) 给出)并且可以获得第一个值。这是通过窗口函数first_value() 完成的,它为您提供有序组的第一个值。要获得最后一个值,您只需对组进行降序排序。 (Why not using last_value())
  5. DISTINCT ON 仅过滤(生成SUM() 函数)组的第一行

【讨论】:

  • 补充说明
  • 非常感谢您的额外解释和您的询问!我很清楚,我得到了我想要的 :D S-Man 节日快乐!
猜你喜欢
  • 2019-05-29
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
  • 2019-10-30
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多