如何获取按id分区的表中的下一个非零值?

oewdyzsn  于 2022-10-22  发布在  其他
关注(0)|答案(4)|浏览(188)

这是我的表的子集:
|id |日期|值|
| ------------ | ------------ | ------------ |
| 1 | 01/01/2022 | 5 |
| 1 | 02/02/2022 | 0 |
| 1 | 03/01/2022 | 0 |
| 1 | 04/02/2022 | 10 |
| 2 | 01/04/2022 | 5 |
| 2 | 02/04/2022 | 3 |
| 2 | 03/04/2022 | 0 |
| 2 | 04/04/2022 | 10 |
如果值字段中有0,我希望将它们替换为非零值,该非零值出现在0序列结束后,按id进行分区。
我尝试过使用LAG,但我真的很难,因为它的值高于表中的当前值。
任何帮助都将不胜感激。
转换后的表格外观
|id |日期|值|
| ------------ | ------------ | ------------ |
| 1 | 01/01/2022 | 5 |
| 1 | 02/02/2022 | 10 |
| 1 | 03/01/2022 | 10 |
| 1 | 04/02/2022 | 10 |
| 2 | 01/04/2022 | 5 |
| 2 | 02/04/2022 | 3 |
| 2 | 03/04/2022 | 10 |
| 2 | 04/04/2022 | 10 |

bprjcwpo

bprjcwpo1#

您可以使用交叉应用;

select T1.id, T1.date, CASE WHEN T1.value = 0 THEN X.value ELSE T1.value END value from TestTable T1
OUTER APPLY (SELECT TOP 1 * FROM TestTable T2
             WHERE T1.id = T2.id AND T2.date > T1.date
             AND T2.value > 0
             ORDER BY T2.date) X

方形底座

cwtwac6a

cwtwac6a2#

假设用替换它们表示要更新表,最简单的方法是关联子查询:

update t set value = (
    select top(1) value
    from t t2
    where t2.id = t.id 
      and t2.value > 0 
      and t2.date > t.date
    order by t2.date
)
where t.value = 0;
mwg9r5ms

mwg9r5ms3#

我们用0后面的第一个非0值对每个0进行分组,然后使用max() over()替换组中的0。

select   id
        ,date
        ,max(value) over(partition by id, grp) as value
from
(
select   *
        ,count(case when value != 0 then 1 end) over(partition by id order by date desc) as grp
from     t
) t
order by id, date
id日期
12022-01-015
12022-02-0210
12022-03-0110
12022-04-0210
22022-01-045
22022-02-043
22022-03-0410
22022-04-0410

Fiddle

sd2nnvve

sd2nnvve4#

您可以使用outer apply来完成:

select
  d.id, d.date_, 
  case when d.value != 0 then d.value else nz.value end as value
from data d
  outer apply (
    select min(value) as value
    from data dd
    where dd.id = d.id
      and dd.date_ > d.date_
      and dd.value <> 0
  ) nz

您可以在此db<>fiddle上进行测试

相关问题