日期:2014-05-18  浏览次数:20662 次

求助剔除错误值的方法
我有一个电量数据表,表结构如下,T_MeterOrigValue:
F_OrigValueID F_MeterID F_CollectTime F_OrigValue
0000001 M001 2011-12-01 12:02 10.5
0000002 M001 2011-12-01 12:22 9.0 -- 错误值需要剔除
0000003 M001 2011-12-01 13:02 12.5
0000004 M001 2011-12-01 13:42 0 -- 错误值需要剔除
0000005 M001 2011-12-01 13:52 0 -- 错误值需要剔除
0000006 M001 2011-12-01 12:02 14.5
0000007 M002 2011-12-01 13:02 200.5
0000008 M002 2011-12-01 14:02 210.5
0000009 M002 2011-12-01 14:42 0 -- 错误值需要剔除
00000010 M002 2011-12-01 15:02 220.5
....
F_OrigValueID为主键,记录的编号,数据有几十万到上百万条,其中仪表编号 F_MeterID 有三百多个,现在想剔除错误值, 当仪表编号与时间排序后,后面时间的数值小于前面的值就认为数值有误,请问如何写sql语句剔除错误值?请高手指教。
我自己有写了一个针对一个仪表的错误值剔除语句,但是效率很低,如果是三百多个仪表这样执行,时间要很长,语句如下,还望高手指点:

DECLARE @f_del int
set @f_del = 1
while @f_del > 0
begin
;with T as
(
select RN=Row_number()OVER(ORDER BY F_CollectTime),F_OrigValueID,F_OrigValue 
from T_MeterOrigValue
where F_MeterID = '001'
)
delete from T_MeterOrigValue
where F_OrigValueID in 
(
select a.F_OrigValueID
from T a 
LEFT JOIN T b 
on (b.Rn + 1 = a.Rn) and (convert(numeric(18, 4),a.F_OrigValue) < convert(numeric(18, 4),b.F_OrigValue))
where b.RN > 0 
)
set @f_del = @@rowCount
end

------解决方案--------------------
declare @t table 
(F_OrigValueID varchar(8),F_MeterID varchar(4),F_CollectTime datetime,F_OrigValue numeric(4,2))

insert into @t
select '0000001','M001','2011-12-01 12:02',10.5 union all
select '0000002','M001','2011-12-01 12:22',9.0 union all
select '0000003','M001','2011-12-01 13:02',12.5 union all
select '0000004','M001','2011-12-01 13:42',0 union all
select '0000005','M001','2011-12-01 13:52',0 union all
select '0000006','M001','2011-12-01 12:02',14.5 union all
select '0000007','M002','2011-12-01 13:02',2.1 union all
select '0000008','M002','2011-12-01 14:02',2.25 union all
select '0000009','M002','2011-12-01 14:42',0 union all
select '00000010','M002','2011-12-01 15:02',2.45

select a.* from @t a 
left join @t b on a.F_OrigValueID+0=b.F_OrigValueID+1 and a.F_MeterID=b.F_MeterID
where a.F_OrigValue>=b.F_OrigValue 
and a.F_OrigValue+b.F_OrigValue<>0 or b.F_OrigValueID is null
/*
F_OrigValueID F_MeterID F_CollectTime F_OrigValue
------------- --------- ----------------------- ---------------------------------------
0000001 M001 2011-12-01 12:02:00.000 10.50
0000003 M001 2011-12-01 13:02:00.000 12.50
0000006 M001 2011-12-01 12:02:00.000 14.50
0000007 M002 2011-12-01 13:02:00.000 2.10
0000008 M002 2011-12-01 14:02:00.000 2.25
00000010 M002 2011-12-01 15:02:00.000 2.45
*/