Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server T-SQL查询更新空值_Sql Server_Tsql_Common Table Expression - Fatal编程技术网

Sql server T-SQL查询更新空值

Sql server T-SQL查询更新空值,sql-server,tsql,common-table-expression,Sql Server,Tsql,Common Table Expression,我在T-SQL中有一个非常具体的问题 如果我能解决我给你们的这个例子,我想我就能解决我原来的案例 将此数据保存在表中: DECLARE @Test TABLE ( Value INT ,Date DATETIME2(7) ); INSERT INTO @Test VALUES (NULL, '2011-01-01 10:00'), (NULL, '2011-01-01 11:00'), (2, '2011-01-01 12:00'), (NULL, '2011-01-01 13

我在T-SQL中有一个非常具体的问题

如果我能解决我给你们的这个例子,我想我就能解决我原来的案例

将此数据保存在表中:

DECLARE @Test TABLE
(
    Value INT
    ,Date DATETIME2(7)
);

INSERT INTO @Test
VALUES
(NULL, '2011-01-01 10:00'),
(NULL, '2011-01-01 11:00'),
(2, '2011-01-01 12:00'),
(NULL, '2011-01-01 13:00'),
(3, '2011-01-01 14:00'),
(NULL, '2011-01-01 15:00'),
(NULL, '2011-01-01 16:00'),
(4, '2011-01-01 17:00'),
(NULL, '2011-01-01 18:00'),
(5, '2011-01-01 19:00'),
(6, '2011-01-01 20:00')
我需要选择此输出:

Value   Date
2       2011-01-01 10:00
2       2011-01-01 11:00
2       2011-01-01 12:00
2       2011-01-01 13:00
3       2011-01-01 14:00
3       2011-01-01 15:00
3       2011-01-01 16:00
4       2011-01-01 17:00
4       2011-01-01 18:00
5       2011-01-01 19:00
6       2011-01-01 20:00
解释一下。如果某个地方的值为空,我需要使用前一小时的值进行更新。如果一行中有多个空值,则具有非空值的最近的前一小时将传播并填充所有这些空值。此外,如果一天中的第一个小时为空,那么一天中具有非空值的最早小时向下传播,如本例中的2。在您的例子中,您可以假设至少有一个值是非空值


我的目标是用常用的表表达式或类似的东西来解决这个问题。如果我尝试使用光标方式,我想我会在短时间内找到解决方案,但我尝试使用CTE和递归CTE的尝试到目前为止都失败了。

由于您的条件并不总是相同的,所以这有点困难。在您的示例中,前两行需要从日期较晚的第一个值获取其值,在其他情况下,它们需要从以前的日期获取值。如果您总是需要查看以前的日期,您可以简单地执行以下查询:

SELECT  B.Value,
        A.[Date]
FROM @Test A
OUTER APPLY (SELECT TOP 1 *
             FROM @Test
             WHERE [Date] <= A.[Date] AND Value IS NOT NULL
             ORDER BY [Date] DESC) B
选择B.值,
A.[日期]
来自@Test A
外部应用(选择顶部1*
来自@Test
其中[Date]请尝试以下操作:

select 
    t.value, t.date
      ,COALESCE(t.value
               ,(select MAX(tt.value) from @Test tt WHERE t.Date>tt.Date)
               ,(SELECT MIN(ttt.Value) FROM @Test ttt Where ttt.Date IS NOT NULL)
               ) AS UseValue
    from @Test   t
输出:

value       date                    UseValue
----------- ----------------------- -----------
NULL        2011-01-01 10:00:00.000 2
NULL        2011-01-01 11:00:00.000 2
2           2011-01-01 12:00:00.000 2
NULL        2011-01-01 13:00:00.000 2
3           2011-01-01 14:00:00.000 3
NULL        2011-01-01 15:00:00.000 3
NULL        2011-01-01 16:00:00.000 3
4           2011-01-01 17:00:00.000 4
NULL        2011-01-01 18:00:00.000 4
5           2011-01-01 19:00:00.000 5
6           2011-01-01 20:00:00.000 6

您尝试过什么?发布您到目前为止所做的事情很有帮助-您可能很接近,只需要一些建议来更正您现有的查询。因为我不知道一行中有多少空值,所以前一个小时的单个连接是不够的。因为我想也许我可以用递归的方式解决它。我只使用了CTE re诅咒是经典的层次结构方式,但我的想法是,如果我可以在递归中每次更新一个空值,也许我可以将它们全部填充。实际上,我在尝试这个想法时很早就失去了它。因此我不相信有什么帮助。在您的示例中,
s不会随着
日期
的增加而减少。是吗这是巧合,还是永远如此?+1表示实际包含“起点”关于工作表和数据插入代码,当我实际接受另一个答案时,我有点太快了。它只处理每小时增加的样本数据。这是正确的答案,它给了我正确的结果。但是我的真实数据有可怕的性能问题。你有什么建议吗你想提高一点性能吗?@John-是的,它肯定会有糟糕的性能,因为你至少要通过两次表
测试
。你知道,第二个
外部应用
只在第一个值为
NULL
时才存在,也许你可以用更好的方法避免。我假设您至少在
Date
列上有一个索引。起初我接受了这个答案,但实际上我使用了上面的另一个解决方案,因为我认为这两个解决方案都有效。但是现在当我在另一个解决方案中遇到一些性能问题时,我开始尝试这个解决方案,发现它不起作用。它只在这个示例中有效,因为值每小时都在增加。试着将值移动一点,看看会发生什么:)@John,如果你有一个正确的PK!
value       date                    UseValue
----------- ----------------------- -----------
NULL        2011-01-01 10:00:00.000 2
NULL        2011-01-01 11:00:00.000 2
2           2011-01-01 12:00:00.000 2
NULL        2011-01-01 13:00:00.000 2
3           2011-01-01 14:00:00.000 3
NULL        2011-01-01 15:00:00.000 3
NULL        2011-01-01 16:00:00.000 3
4           2011-01-01 17:00:00.000 4
NULL        2011-01-01 18:00:00.000 4
5           2011-01-01 19:00:00.000 5
6           2011-01-01 20:00:00.000 6