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

Posted

技术标签:

【中文标题】SQL 状态随开始日期和结束日期而变化【英文标题】:SQL status changes with start and end dates 【发布时间】:2021-11-25 10:50:17 【问题描述】:

这是 2021 年 9 月 1 日至 2021 年 9 月 10 日期间用户状态的表格。 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

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

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

【问题讨论】:

不会按开始日期订购,状态工作? 【参考方案1】:

更新

这里是一个例子: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 

【讨论】:

嗯,当用户在取消后再次变得活跃时,这似乎没有捕捉到。如果用户活动或取消仅一天,它也不会返回正确的结束日期。 @bbk611 我更新了答案。我想,现在运行,你是如何描述它的。 那也行不通。在您的示例表中,每个用户的状态,无论是活动还是取消,都只占用一行。在我提供的表格中,每个用户有时会在超过一天的时间内处于活跃或取消状态。所以他们的状态有时会占据不止一排。【参考方案2】:

我想通了。

关键组件在当前状态不等于先前状态时进行过滤。这表示用户状态更改的日期。

当您过滤这些行时,您只需使用 LEAD() 窗口函数并减去 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

【讨论】:

以上是关于SQL 状态随开始日期和结束日期而变化的主要内容,如果未能解决你的问题,请参考以下文章

SQL 'overlaps' 仅获取开始和结束之间的日期(不包括开始和结束日期)

如果开始日期和结束日期跨越一个或多个月,则插入表格时日期格式会发生变化

如何通过在 SQL Server 中选择周数来获取开始日期和结束日期

sql server 中两个日期之间的年份以及每个日期在 sql server 中的开始和结束日期

调整开始和结束日期sql

SQL 日期过滤器:当开始日期 = 结束日期时返回结果