我正在编写一些代码,以便在7天的滚动窗口中寻找最小值。
首先,我要找到每天的最小值并将其插入临时表#minimumvalue 这是考虑到存在多个值的天数。
我正在使用min(Value) over(partition by ID order by Date_Value rows between 6 preceding and current row
来找到rolling_min值,这就是我得到的
ID | Date_Value | Value | rolling_min
1234 1-1-2018 12:15 pm 2.95 1.54
1234 1-1-2018 3:30 pm 1.54 1.54
1234 1-2-2018 10:45 am 1.57 1.54
1234 1-3-2018 2:15 pm 2.02 1.54
1234 1-4-2018 4:00 pm 2.80 1.54
1234 1-5-2018 NULL 1.54
1234 1-6-2018 NULL 1.54
1234 1-7-2018 NULL 1.56
1234 1-8-2018 NULL 1.57
前2行在同一天发生,因此rolling_min以1.54开始。确实应该从2.95开始,因为这是当前的最低要求。
从那里我想找到第一个实例,该实例的最小数量增加了 1.85。
我尝试了一个案例声明CASE WHEN Value >= 1.85 * MIN(Value) OVER(PARTITION BY ID ORDER BY Date_Value ROWS BETWEEN 6 PRECEDING and CURRENT ROW
THEN 1
ELSE 0
END AS Increase YN
这是结果
ID | Date_Value | Value | rolling_min | Increase YN
1234 1-1-2018 12:15 pm 2.95 1.54 1
1234 1-1-2018 3:30 pm 1.54 1.54 0
1234 1-2-2018 10:45 am 1.57 1.54 0
1234 1-3-2018 2:15 pm 2.02 1.54 0
1234 1-4-2018 4:00 pm 2.80 1.54 1
1234 1-5-2018 NULL 1.54 0
1234 1-6-2018 NULL 1.54 0
1234 1-7-2018 NULL 1.57 0
1234 1-8-2018 NULL 1.57 0
第一行显示1,因为它是1.85 * 1.54的最小值,但之后是1.54,所以这并不是我真正想要的。我该如何避免这种情况,而只在增加的地方返回1?
在此先感谢您的帮助:)
答案 0 :(得分:2)
我认为您正在尝试首次发现任何数据值比最近6天的最小值都高出85%。我希望那是正确的。
这是我的代码:
create table data
(ID int not null,
Date_Value datetime not null,
Value decimal(5,2)
)
go
truncate table data
go
insert into data
select 1234, '2018-01-01 12:15:00', 2.95
union all select 1234, '2018-01-01 12:15:00', 1.54
union all select 1234, '2018-01-02 10:45:00', 1.57
union all select 1234, '2018-01-03 14:15:00', 2.02
union all select 1234, '2018-01-04 16:00:00', 2.80
union all select 1234, '2018-01-05', null
union all select 1234, '2018-01-06', null
union all select 1234, '2018-01-07', null
union all select 1234, '2018-01-08', null
union all select 1234, '2018-01-09 09:00:00', 3.4
union all select 1234, '2018-01-09 10:00:00', 5.4
union all select 1234, '2018-01-09 11:00:00', 8.4
go
insert into data
select 9999, '2018-01-01 12:15:00', 2.95
union all select 9999, '2018-01-01 12:15:00', 1.54
union all select 9999, '2018-01-02 10:45:00', 1.57
union all select 9999, '2018-01-03 14:15:00', 2.02
union all select 9999, '2018-01-04 16:00:00', 2.80
union all select 9999, '2018-01-05', null
union all select 9999, '2018-01-06', null
union all select 9999, '2018-01-07', null
union all select 9999, '2018-01-08', null
union all select 9999, '2018-01-09 09:00:00', 3.4
union all select 9999, '2018-01-09 10:00:00', 5.4
union all select 9999, '2018-01-09 11:00:00', 8.4
go
;with ByDayMin as
(
select ID, Date_Value = cast(Date_Value as date), Value=min(Value)
from data
group by ID, cast(Date_Value as date)
),
IncBig as (
select ID, Date_Value,
Value,
sixDayMin = MIN(Value) OVER(PARTITION BY ID ORDER BY Date_Value ROWS BETWEEN 6 PRECEDING and CURRENT ROW)
from ByDayMin
),Calcs as
(
select d.*,
i.SixDayMin,
ValueIncreaseRatioLast6Days = d.Value / SixDayMin,
Prior = LAG(d.Date_Value, 1,null) OVER(PARTITION BY d.ID ORDER BY d.Date_Value)
from data d
join ByDayMin b
on b.ID = d.ID
and b.Date_Value = cast(d.Date_Value as date)
join IncBig i
on i.ID = d.ID
and i.Date_Value = b.Date_Value
)
select c.ID, c.Date_Value, c.Value, c.SixDayMin, ValueIncreaseRatioLast6Days,
Increase_YN=case when c.ValueIncreaseRatioLast6Days >= 1.85
and not exists (select 1 from Calcs c2
where c2.ID = c.ID
and c2.ValueIncreaseRatioLast6Days >= 1.85
and c2.Date_Value < c.Date_Value
and Prior is not Null
)
and Prior is not Null
then 1
else 0
end
from Calcs c
order by c.ID, c.Date_Value