这是我的桌子。
Site_name | date& Time | PowerOutput
----------+-------------------------+------------------
ACT0001 | 2013-07-21 01:00:00.000 | 196.852984494331
ACT0001 | 2013-07-21 02:00:00.000 | 0
xyz0001 | 2013-07-21 03:00:00.000 | 196.852984494331
xyq0001 | 2013-07-21 04:00:00.000 | 196.958395639561
xys0001 | 2013-07-21 05:00:00.000 | 0
xyd0001 | 2013-07-21 06:00:00.000 | 197.20098185022
xye0001 | 2013-07-21 07:00:00.000 | 0
xyg0001 | 2013-07-21 08:00:00.000 | 0
cfg0001 | 2013-07-21 09:00:00.000 | 197.412144323522
acb0001 | 2013-07-21 10:00:00.000 | 0
bdf0001 | 2013-07-21 11:00:00.000 | 0
olk0001 | 2013-07-21 12:00:00.000 | 196.886233049016
我正在尝试更新零位的值。如果只有一个零,那么我可以更新表,但是如果有连续的零,我发现很难更新表。
逻辑是:
((Previous value-next value)/previous value)*100 <5
如果这是真的那么它应该插入先前的值
((Previous value-next value)/previous value)*100 >=5
如果这是真的那么它应该保持为零。
这是我到目前为止的代码:
;with cte as
(
SELECT
*,
lead(pr_output,1) OVER (ORDER BY (select null)) As PreviousValue,
lag(pr_output,1) OVER (ORDER BY (select null)) As NextValue
FROM
[dbo].[My_table]
)
,ctee as
(
select
*,
abs((PreviousValue*100-NextValue*100)/(case when NextValue = 0 then 1 else NextValue end)) as CheckFlag
from
cte
)
select
Site_name,[DATE&Time],
case
when pr_output <>0 then pr_output
else
case
when CheckFlag >= 5 then 0
else PreviousValue
end
end as pr_output
from
ctee
如果连续零,我无法更新记录。
预期产出:
Site_name | date& Time | PowerOutput
----------+-------------------------+------------------
ACT0001 | 2013-07-21 01:00:00.000 | 196.852984494331
ACT0001 | 2013-07-21 02:00:00.000 | 196.852984494331
xyz0001 | 2013-07-21 03:00:00.000 | 196.852984494331
xyq0001 | 2013-07-21 04:00:00.000 | 196.958395639561
xys0001 | 2013-07-21 05:00:00.000 | 196.958395639561
xyd0001 | 2013-07-21 06:00:00.000 | 197.20098185022
xye0001 | 2013-07-21 07:00:00.000 | 197.20098185022
xyg0001 | 2013-07-21 08:00:00.000 | 197.20098185022
cfg0001 | 2013-07-21 09:00:00.000 | 197.412144323522
acb0001 | 2013-07-21 10:00:00.000 | 197.412144323522
bdf0001 | 2013-07-21 11:00:00.000 | 197.412144323522
olk0001 | 2013-07-21 12:00:00.000 | 196.886233049016
谢谢
答案 0 :(得分:1)
如果你要做的是将PowerOutput
中的任何零值替换为最新的先前非零PowerOutput值,仅在以下情况下:
((Previous value-next value)/previous value)*100 <5
然后我相信这就是诀窍:
SELECT main.SiteName,
main.[DateTime],
CASE WHEN main.PowerOutput = 0
THEN CASE WHEN ((PreviousNonZero.PowerOutput - NextNonZero.PowerOutput) / PreviousNonZero.PowerOutput) * 100 < 5
THEN PreviousNonZero.PowerOutput
ELSE 0
END
ELSE main.PowerOutput
END AS PowerOutput
FROM [dbo].[My_table] main
OUTER APPLY
(
SELECT TOP 1 PowerOutput
FROM [dbo].[My_table] prev
WHERE prev.[DateTime] < main.[DateTime]
AND PowerOutput <> 0
ORDER BY prev.[DateTime] DESC
) PreviousNonZero
OUTER APPLY
(
SELECT TOP 1 PowerOutput
FROM [dbo].[My_table] future
WHERE future.[DateTime] > main.[DateTime]
AND PowerOutput <> 0
ORDER BY future.[DateTime]
) NextNonZero
ORDER BY [DateTime]
我不确定是否:
((Previous value-next value)/previous value)*100 <5
实际上是你想要使用的逻辑。您似乎正在尝试确定该值是否从之前的非零值更改为或低于5%到下一个值,但这仅在更改始终在一个方向上发生时才起作用,否则您会得到一些否定值值也是(您的样本数据集具有此计算的值,范围从约-0.23到0.27)。
如果你想要的是识别PowerOutput
值变化超过5%(在任一方向上)的实例,我会改变上面查询中的内部CASE
语句:
CASE WHEN ((PreviousNonZero.PowerOutput - NextNonZero.PowerOutput) / PreviousNonZero.PowerOutput) * 100 < 5
为:
CASE WHEN (ABS(PreviousNonZero.PowerOutput - NextNonZero.PowerOutput) / PreviousNonZero.PowerOutput) * 100 < 5
答案 1 :(得分:1)
我使用标量函数做了不同的方法
CREATE FUNCTION [dbo].[fnGetAvgPower]
(
@site_name varchar(50), @date_time datetime
)
RETURNS decimal(24,12) --Check the number of decimal you need here
AS
BEGIN
--
DECLARE @AvgPower decimal(24,12), @PrevValue decimal(24,12),@NextValue decimal(24,12), @Value decimal(24,12)--Check the number of decimal you need here
set @PrevValue = (Select Top 1 PowerOutput from Table_3 where Site_name = @site_name and datestamp < @date_time and PowerOutput <> 0
order by datestamp desc)
set @NextValue = (Select Top 1 PowerOutput from Table_3 where Site_name = @site_name and datestamp > @date_time and PowerOutput <> 0
order by datestamp asc)
set @Value = @PrevValue / @NextValue * 100
if(@Value is null)
begin
set @Value= 0
end
else
begin
set @Value = (Select case when @Value > 5 then @PrevValue when @Value <= 5 then 0 end)
end
RETURN @Value
-- Call funtion
update Table_3 set PowerOutput = dbo.fnGetAvgPower(Site_name,datestamp)
where PowerOutput = 0