我有一个包含以下架构的表:
DateTime [Creation Date] PK
int [Data]
列数据具有来自传感器的值,如下所示:
123
225
354
578
0
2151
2331
0
2555
2678
正如您所看到的,值总是递增。
由于传感器存在问题,我们有时会在有效值之间获得0。当我们尝试使用数据时,这会产生一些问题,因此我们希望用某些东西来填补这些空白。理想情况下,我们希望在上一个值和下一个值之间加上平均值,如果不可能,我们想重复之前的值。
这只是一个问题吗?
提前致谢。
答案 0 :(得分:3)
也许不是最有效的,但应该有效:
WITH cte
AS (SELECT [Creation Date],
Data,
rn=Row_number() OVER(ORDER BY [Creation Date])
FROM dbo.Table)
UPDATE cte
SET Data = ( ( (SELECT c2.Data
FROM cte c2
WHERE c2.rn = cte.rn - 1)
+ (SELECT c2.Data
FROM cte c2
WHERE c2.rn = cte.rn + 1) ) / 2 )
WHERE Data = 0;
我在CTE中使用Row_Number
来获取Creation Date
排序的连续数字。然后,此数字用于根据其上一个和下一个值获取新数据。
Here's具有类似架构的演示(我使用int
代替datetime
):
更新
很好,但它没有处理多个0的差距
好的捕获,这是修改后的sql,它考虑到了这一点:
WITH cte
AS (SELECT [Creation Date],
Data,
rn=Row_number() OVER(ORDER BY [Creation Date])
FROM dbo.Table)
UPDATE cte
SET Data = ( ( (SELECT c2.Data
FROM cte c2
WHERE c2.rn = (SELECT MAX(RN)FROM CTE c3 WHERE c3.RN<cte.RN AND c3.Data<>0))
+ (SELECT c2.Data
FROM cte c2
WHERE c2.rn = (SELECT MIN(RN)FROM CTE c3 WHERE c3.RN>cte.RN AND c3.Data<>0))) / 2 )
WHERE Data = 0;
Demo(在5,6上连续为零)
答案 1 :(得分:1)
我有另一种变化:
SELECT
BadDate,
T1.Data AS PrevData,
T2.Data AS NextData,
(T1.Data + T2.Data) / 2 AS AvgValue
FROM
(
SELECT
T1.CreationDate As BadDate,
Max(T2.CreationDate) As PrevDate,
Min(T3.CreationDate) As NextDate
FROM
TestData T1,
TestData T2,
TestData T3
WHERE
T1.Data = 0
AND T2.Data <> 0
AND T2.CreationDate < T1.CreationDate
AND T3.Data <> 0
AND T3.CreationDate > T1.CreationDate
GROUP BY T1.CreationDate
) DateData
INNER JOIN TestData T1
ON DateData.PrevDate = T1.CreationDate
INNER JOIN TestData T2
ON DateData.NextDate = T2.CreationDate
答案 2 :(得分:0)
如果您不担心获得平均值,此方法可以为之前的值添加数字。
另请注意,我不确定此方法是否有任何问题(除了更新所有记录),但仅仅显示为一种不同且简单的方法......
declare @new int = 1
update mytable
set @new = val = case when val = 0 then @new + 1 else val end
| D | VAL |
---------------------
| 2013-01-01 | 123 |
| 2013-01-02 | 225 |
| 2013-01-03 | 354 |
| 2013-01-04 | 578 |
| 2013-01-05 | 579 |--Updated
| 2013-01-06 | 2151 |
| 2013-01-07 | 2331 |
| 2013-01-08 | 2332 |--Updated
| 2013-01-09 | 2555 |
| 2013-01-10 | 2678 |
答案 3 :(得分:0)
还有一个选择
UPDATE s
SET s.Data = (COALESCE(o1.Data, o2.Data) + COALESCE(o2.Data, o1.Data)) / 2
FROM dbo.sensor s OUTER APPLY (
SELECT TOP 1 s2.Data AS Data
FROM dbo.sensor s2
WHERE s2.Data != 0 AND s.[Creation Date] < s2.[Creation Date]
ORDER BY s2.[Creation Date] ASC
) o1
OUTER APPLY (
SELECT TOP 1 s3.Data AS Data
FROM dbo.sensor s3
WHERE s3.Data != 0 AND s.[Creation Date] > s3.[Creation Date]
ORDER BY s3.[Creation Date] DESC
) o2
WHERE s.Data = 0
SQLFiddle上的演示