需要帮助向前和向后填写 SQL 查询

Need help in forward and backward filling in SQL query

我需要使用日期列确定每个团队在 x 列和 y 列中花费的时间。为此,我正在处理 x 列的后向填充和 y 列的前向填充,以便我可以计算每个团队的开始时间和结束时间之间的差异。

在前向填充和后向填充方面需要帮助 table。

这是数据现在的样子。

数据如何处理 运行 查询 - X 列向后和 Y 列向前

Number Date Sl_NO Column_X Column_Y Column_X_Backward Column_Y_Forward
1 44563 1 NULL NULL A NULL
1 44563 2 A B A B
1 44563 3 NULL NULL C B
1 44563 4 NULL NULL C B
1 44563 5 NULL NULL C B
1 44563 6 NULL NULL C B
1 44563 7 C D C D
1 44563 8 NULL NULL E D
1 44563 9 E F E F
1 44563 10 NULL NULL NULL F
1 44563 11 NULL NULL NULL F
1 44563 12 NULL NULL NULL F
2 44563 1 NULL NULL A NULL
2 44563 2 A B A B
2 44563 3 NULL NULL C B
2 44563 4 NULL NULL C B
2 44563 5 C D C D
2 44563 6 NULL NULL E D
2 44563 7 E B E B
2 44563 8 NULL NULL B B
2 44563 9 NULL NULL B B
2 44563 10 B A B A
2 44563 11 NULL NULL NULL A
2 44563 12 NULL NULL NULL A

这里的 X 列必须回填到前一个值,它应该在相同的数字内,Y 列必须向前填充到相同数字内的下一个值。

希望有人能够帮助我解决同样的问题。

您可以使用标量子查询来完成。不幸的是,只有 Sql 服务器的 Azur 版本支持 first_value() 函数中的 IGNORE NULLS 选项。

select t1.* 
    , coalesce(Column_X, 
       (select top(1) t2.Column_X 
        from mytable t2 
        where t2.Number = t1.Number and t2.Column_X is not null and t2.Sl_NO > t1.Sl_NO order by Sl_NO)) x2
    , coalesce(Column_Y,
       (select top(1) t2.Column_Y 
        from mytable t2 
        where t2.Number = t1.Number and t2.Column_X is not null and t2.Sl_NO < t1.Sl_NO order by Sl_NO desc)) y2
from mytable t1

这是 lptr 作为评论发布的。我将其作为社区维基答案发布以保存它,以防评论再次被删除。

他们在这里使用派生的 table 来执行窗口聚合,执行“累积”计数。然后他们使用派生的 table 获得 MAX 值,这些值再次被窗口化。

create table t(Number int, Date int, Sl_NO int, Column_X char(1), Column_Y char(1))

insert into t(Number, Date, Sl_No, Column_X, Column_Y)
values
(1, 44563, 1, NULL, NULL),
(1, 44563, 2, 'A', 'B'),
(1, 44563, 3, NULL, NULL),
(1, 44563, 4, NULL, NULL),
(1, 44563, 5, NULL, NULL),
(1, 44563, 6, NULL, NULL),
(1, 44563, 7, 'C', 'D'),
(1, 44563, 8, NULL, NULL),
(1, 44563, 9, 'E', 'F'),
(1, 44563, 10, NULL, NULL),
(1, 44563, 11, NULL, NULL),
(1, 44563, 12, NULL, NULL),

(2, 44563, 1, NULL, NULL),
(2, 44563, 2, 'A', 'B'),
(2, 44563, 3, NULL, NULL),
(2, 44563, 4, NULL, NULL),
(2, 44563, 5, 'C', 'D'),
(2, 44563, 6, NULL, NULL),
(2, 44563, 7, 'E', 'B'),
(2, 44563, 8, NULL, NULL);

select Number, Date, Sl_No, 
    Column_X,
    max(Column_X) over(partition by Number, Date, cntColumn_X) as Column_X_Backward,
    Column_Y,
    max(Column_Y) over(partition by Number, Date, cntColumn_Y) as Column_Y_Forward
from
(
select *, 
  count(Column_X) over(partition by Number, Date order by Sl_NO rows between unbounded preceding and 1 preceding) as cntColumn_X,
  count(Column_Y) over(partition by Number, Date order by Sl_NO) as cntColumn_Y
from t
) as t

db<>fiddle