Sql 从上一行更新记录

Sql 从上一行更新记录,sql,sql-server,sql-server-2008,sql-update,Sql,Sql Server,Sql Server 2008,Sql Update,SQL Server 2008 R2 请参阅下表: Device | DateOfSample| Value ================================= Pump 1 Starts| 2020-07-07| 0 Pump 1 Starts| 2020-07-08| 32 Pump 1 Starts| 2020-07-09| 30 Pump 1 Starts| 2020-07-10| 5 Pump 1 Starts| 2020-07-1

SQL Server 2008 R2

请参阅下表:

Device       | DateOfSample|  Value
=================================
Pump 1 Starts| 2020-07-07|    0
Pump 1 Starts| 2020-07-08|    32
Pump 1 Starts| 2020-07-09|    30
Pump 1 Starts| 2020-07-10|    5
Pump 1 Starts| 2020-07-11|    29
Pump 1 Starts| 2020-07-12|    0
Pump 1 Starts| 2020-07-13|    57
Pump 1 Starts| 2020-07-14|    50
Pump 1 Starts| 2020-07-15|    0
Pump 1 Starts| 2020-07-16|    52
如果值为0,我需要更新值表,使其具有前几天的值,以便如下所示:

Device       | DateOfSample|  Value
=================================
Pump 1 Starts| 2020-07-07|    0
Pump 1 Starts| 2020-07-08|    32
Pump 1 Starts| 2020-07-09|    30
Pump 1 Starts| 2020-07-10|    5
Pump 1 Starts| 2020-07-11|    29
Pump 1 Starts| 2020-07-12|    29
Pump 1 Starts| 2020-07-13|    57
Pump 1 Starts| 2020-07-14|    50
Pump 1 Starts| 2020-07-15|    50
Pump 1 Starts| 2020-07-16|    52
如果表中的第一个值为0,我不希望它发生更改,但任何其他0值都需要与前一天一样记录

我一直在尝试使用Update Case,但似乎没有任何进展

UPDATE #MaxValues
    SET Value = CASE
    WHEN m.Value = 0 THEN (
        SELECT m1.Value
        FROM #MaxValues m1
        WHERE m1.DateOfSample = DateAdd (Day, -1, (SELECT m2.DateOfSample FROM #MaxValues m2 WHERE Value = 0)))
    ELSE m.Value
    END
FROM #MaxValues AS m
我得到的只是一个错误:

Msg 512,16级,状态1,程序sp_PumpStartAvg,第156行 子查询返回了多个值。当子查询在=、!=、=或者当子查询用作表达式时

我知道为什么会出现错误,这是因为表中有多个位置有0,我试图在日期选择语句中返回所有位置。我只是不知道该怎么解决这个问题

非常感谢您的建议。

尝试以下方法:

DECLARE @DataSource TABLE
(
    [Device] VARCHAR(16)
   ,[DateOfSample] DATE
   ,[Value] INT
);

INSERT INTO @DataSource ([Device], [DateOfSample], [Value])
VALUES ('Pump 1 Starts', '2020-07-07', 0)
      ,('Pump 1 Starts', '2020-07-08', 32)
      ,('Pump 1 Starts', '2020-07-09', 30)
      ,('Pump 1 Starts', '2020-07-10', 5)
      ,('Pump 1 Starts', '2020-07-11', 29)
      ,('Pump 1 Starts', '2020-07-12', 0)
      ,('Pump 1 Starts', '2020-07-13', 57)
      ,('Pump 1 Starts', '2020-07-14', 50)
      ,('Pump 1 Starts', '2020-07-15', 0)
      ,('Pump 1 Starts', '2020-07-16', 52);

UPDATE DS1
SET [Value] = DS2.[Value]
FROM @DataSource DS1
INNER JOIN @DataSource DS2
    ON DS1.[Device] = DS2.[Device]
    AND DS1.[DateOfSample] = DATEADD(DAY, 1, DS2.[DateOfSample])
WHERe DS1.[Value] = 0


SELECT *
FROM @DataSource
ORDER BY [Device]
        ,[DateOfSample];

您可以使用DateTime函数Datediff查找以前的日期。请尝试此查询:

Update t2
Set t2.Value=t1.Value
FROM Table t1
left join Table t2
on DATEDIFF(dd,t1.DateofSample,t2.DateofSample)=1
and t2.device=t1.device
and t2.Value=0

在SQL Server中,认为最简单和最有效的方法是窗口函数和可更新的CTE:

with cte as (
    select value, lag(value) over(partition by devince order by dateOfSample) lag_value
    from mytable 
)
update cte set value = lag_value
where value = 0 and lag_value is not null

假设“上一行”是指上一个日期,则联接是最佳解决方案:

update t
    set Value = coalesce(t1.Value, 0)
from t left join
     t tprev
     on tprev.DateofSample = dateadd(day, -1, t.DateofSample);

如果说“前一行”实际上是指前一行,即使存在间隙,那么GMB使用lag的解决方案(需要SQL Server 2012)是更好的解决方案。

感谢大家的帮助


我最终通过以不同的方式构建原始表来解决问题。因此根本不需要解决问题。

这是一个迭代过程。至少我认为是这样。如果一天的值为零,而前一个值也为零,则可能需要前一个值之前的行的值-如果该值也不是零;-我不知道SQL Server中的存储过程能做什么,所以我不能说它们在这里是否有帮助。您可以运行递归查询中的值,然后使用找到的值更新零值行。但是,我想,如果这不是数百万行,我只需选择一个应用程序中的所有行,循环遍历它们,然后从那里发布一些必要的更新。@MarkUnderwood。为什么要使用不受支持的SQL Server版本?使用不受支持的版本,因为这是软件包所需的版本。我们正在远离它,但目前还无法摆脱它。除了在年底前查找外,希望将其删除。