SQL 状态随开始日期和结束日期而变化

SQL status changes with start and end dates

这是 2021 年 9 月 1 日至 2021 年 9 月 10 日期间的 table 用户状态。 1 表示“活跃”。 0 表示“已取消”。

date user status
9/1/2021 1 1
9/1/2021 2 0
9/1/2021 3 1
9/2/2021 1 1
9/2/2021 2 1
9/2/2021 3 1
9/3/2021 1 0
9/3/2021 2 1
9/3/2021 3 1
9/4/2021 1 0
9/4/2021 2 1
9/4/2021 3 1
9/5/2021 1 0
9/5/2021 2 1
9/5/2021 3 0
9/6/2021 1 1
9/6/2021 2 1
9/6/2021 3 0
9/7/2021 1 1
9/7/2021 2 1
9/7/2021 3 0
9/8/2021 1 0
9/8/2021 2 1
9/8/2021 3 1
9/9/2021 1 0
9/9/2021 2 1
9/9/2021 3 1
9/10/2021 1 1
9/10/2021 2 0
9/10/2021 3 1

我想获取这段时间内每个用户的活动和取消时段的开始和结束日期。我知道这涉及到 window 函数,但我不太清楚该怎么做。这是我想要的输出:

user status start date end date
1 1 9/1/2021 9/2/2021
1 0 9/3/2021 9/5/2021
1 1 9/6/2021 9/7/2021
1 0 9/8/2021 9/9/2021
1 1 9/10/2021 9/10/2021
2 0 9/1/2021 9/1/2021
2 1 9/2/2021 9/9/2021
2 0 9/10/2021 9/10/2021
3 1 9/1/2021 9/4/2021
3 0 9/5/2021 9/7/2021
3 1 9/8/2021 9/10/2021

已更新

这里有一个例子:fiddle

更新查询,

;with cte as (
         SELECT *,Rank() OVER ( partition by usr,status order by dt )as rnk
        ,LAG(dt,1) OVER (partition by usr order by dt desc) as LAG
        ,Row_number() over (partition by usr order by dt asc) as rnum
        ,count(*) over (partition by usr,status) as cnt
FROM TABLE1

     )
Select usr,status,dt as start_date,LAG as End_date  from cte 

我想通了。

当当前状态不等于先前状态时,关键组件正在过滤。表示用户状态变化的日期。

过滤这些行时,您只需使用 LEAD() window 函数并减去 1 天即可获得该状态的结束日期。

with win as
(
select
  usr
  , dt
  , lag(status) over (partition by usr order by dt) as prev_status
  , status
from subs
)
select
  usr
  , status
  , dt as start_date 
  , coalesce(lead(dt) over (partition by usr order by dt) - interval '1 day', (select max(dt) from win)) as end_date
from win
where
  status <> prev_status
  or prev_status is null