检查连续值,然后做出决定

时间:2019-05-08 07:22:32

标签: sql sql-server lead

我有一个数据集,如果值是0,我需要检查接下来的7个连续日期,然后如果7天之间的值都不为0,我们会将所有中间值都设为0,然后将所有值标记为1.
例如:

数据集

Days       Values  
12/21/2006  1  
12/22/2006  1  
12/23/2006  1  
12/24/2006  1  
12/25/2006  0  
12/26/2006  1  
12/27/2006  0  
12/28/2006  0  
12/29/2006  1  
12/30/2006  1  
12/31/2006  0  
1/1/2007    0  
1/2/2007    0  
1/3/2007    0  
1/4/2007    0  
1/5/2007    0  
1/6/2007    0  
1/7/2007    1  
1/8/2007    1

预期结果

Day      Values NewVal  
12/21/2006  1   1    
12/22/2006  1   1  
12/23/2006  1   1  
12/24/2006  1   1  
12/25/2006  0   1  
12/26/2006  1   1  
12/27/2006  0   1  
12/28/2006  0   1  
12/29/2006  1   1  
12/30/2006  1   1  
12/31/2006  0   0  
1/1/2007    0   0  
1/2/2007    0   0  
1/3/2007    0   0  
1/4/2007    0   0  
1/5/2007    0   0  
1/6/2007    0   0  
1/7/2007    1   1  
1/8/2007    1   1 

我已经尝试使用Lead检查7天的数据,但无法获得连续7天的零部分。在我的代码中,只要它在7天中得到零,就将值设为0而不是我想要的是 。

我的查询是

select *, LEAD(Values,7,0) over (order by gas_dte) as nextval
from temp

2 个答案:

答案 0 :(得分:0)

;with cte as (
    select '12/21/2006' as TheDay, 1 as TheValue union all
    select '12/22/2006' as TheDay, 1 as TheValue union all
    select '12/23/2006' as TheDay, 1 as TheValue union all
    select '12/24/2006' as TheDay, 1 as TheValue union all
    select '12/25/2006' as TheDay, 0 as TheValue union all
    select '12/26/2006' as TheDay, 1 as TheValue union all
    select '12/27/2006' as TheDay, 0 as TheValue union all
    select '12/28/2006' as TheDay, 0 as TheValue union all
    select '12/29/2006' as TheDay, 1 as TheValue union all
    select '12/30/2006' as TheDay, 1 as TheValue union all
    select '12/31/2006' as TheDay, 0 as TheValue union all
    select '01/01/2007' as TheDay, 0 as TheValue union all
    select '01/02/2007' as TheDay, 0 as TheValue union all
    select '01/03/2007' as TheDay, 0 as TheValue union all
    select '01/04/2007' as TheDay, 0 as TheValue union all
    select '01/05/2007' as TheDay, 0 as TheValue union all
    select '01/06/2007' as TheDay, 0 as TheValue union all
    select '01/07/2007' as TheDay, 1 as TheValue union all
    select '01/08/2007' as TheDay, 1 as TheValue
)
-- Define WeekNumber as Year * 100 + week
, set1 as (
    select *, YEAR(TheDay) * 100 + DATEPART(week, TheDay) as WeekNumber
    from cte
)
-- Aggregate Value per WeekNumber
, set2 as (
    select WeekNumber, sum(TheValue) as ValueSum
    from set1
    group by WeekNumber
)
-- Present
select set1.TheDay, set1.TheValue, case when set2.ValueSum > 0 then 1 else 0 end as NewVal
from set1
inner join set2
    on set1.WeekNumber = set2.WeekNumber

答案 1 :(得分:0)

根据您的描述,您可以将min()用作窗口函数:

select t.*,
       min(value) over (order by day rows between current row and 6 following) as newval
from t;

如果您只想保留由7个(或更多)连续的零组成的组,则可以使用窗口函数:

select t.day, t.value,
       (case when value = 0 and count(*) over (partition by value, dateadd(day, -seqnum, day)) >= 7
             then value
             else 1
        end) as newvalue
from (select t.*,
             row_number() over (partition by value order by day) as seqnum
      from t
     ) t;

为此,db <>小提琴是here

此操作的逻辑是简化的“群岛”解决方案。通过减去序号(由row_number()生成)可以找到相邻日期的组。然后case逻辑将保留满足您条件的0