SQL:使用上一行的值填充当前行

时间:2019-03-09 05:55:34

标签: sql sql-server join

我像这样有两个表table1和table2。您会看到时代空白

table1
date      item time amount
----------------------------
1/1/2000  a    1    100
1/1/2000  a    2    100
1/1/2000  a    3    200
1/1/2000  a    6    300
1/1/2000  b    1    100
1/1/2000  b    2    100
1/1/2000  b    5    200
2/1/2000  a    1    500
2/1/2000  a    3    500
2/1/2000  a    4    550

我也有table2可以填补空白

table2
date      item time amount new
-------------------------------------------
1/1/2000  a    1    100    N
1/1/2000  a    2    100    N
1/1/2000  a    3    200    N
1/1/2000  a    4           Y  <-- added amount should be 200
1/1/2000  a    5           Y  <-- added amount should be 200
1/1/2000  a    6    300    N
1/1/2000  b    1    100    N
1/1/2000  b    2    100    N
1/1/2000  b    3           Y  <-- added amount should be 100 
1/1/2000  b    4           Y  <-- added amount should be 100
1/1/2000  b    5    200    N
2/1/2000  a    1    500    N
2/1/2000  a    2    500    N
2/1/2000  a    3           Y  <-- added amount should be 500
2/1/2000  a    4    550    N

金额差距行应采用上次/上次时间的值。我能够识别丢失的行并添加缺口行,但是我尝试将金额复制到缺口行,但未成功。我查看了我认为是stackoverflow中类似问题的内容,并尝试了解决方案,但它没有起作用,例如:

update t2
set t2.amount = t1.amount
from table2 t2
inner join table1 t1 on t2.date = t1.date and t1.item = t2.item
where t2.new = 'Y'
and t2.time > (select t2.time 
              from table1 t3
              where max(t3.time) < t2.time)


update t2
set t2.amount = t1.amount
from table1 t1
inner join table2 t2 on t1.date = t2.date and t1.item = t2.item
where t2.new = 'Y' and max(t1.time) < t2.time     

有人知道如何访问上一行的金额吗?游标有效,但这是不得已的解决方案。感谢您抽出宝贵的时间来帮助您。

添加我的创建表代码

create table #table1  (or #table2)
(
   date smalldatetime,
   item char(1),
   [time] int,
   amount int
   ,new char(1) -- for new row flag 
)

4 个答案:

答案 0 :(得分:2)

您需要找到先前的amount的非空值:

update t
set amount = (
  select amount from table2 
  where
  date = t.date and item = t.item and time = (
    select max(time) from table2
    where 
    date = t.date and item = t.item 
    and time < t.time and amount is not null and new = 'N'
  ) 
)
from table2 t
where t.amount is null and t.new = 'Y'

请参见demo

答案 1 :(得分:0)

您应该使用窗口查询:

select 
*,sum(amount) over (partition by time order by time) as previous_amount_for_null_values
from table2 

答案 2 :(得分:0)

update tab2
set tab2.amount=abc.PREV_AMOUNT
from
table2 tab2
join
(SELECT *,T2.AMOUNT PREV_AMOUNT
FROM TABLE1 T1
JOIN
(
SELECT
MAX(TIME) TIME,DATE,ITEM,MAX(AMOUNT) AMOUNT
FROM TABLE1
WHERE TIME!=(SELECT MAX(TIME) FROM TABLE1
GROUP BY DATE,ITEM)
GROUP BY DATE,ITEM) T2
ON T1.DATE=T2.DATE
AND T1.ITEM=T2.ITEM
AND T1.TIME=T2.TIME) abc
on tab2.date=abc.date
and tab2.item=abc.item
where tab2.new='Y' and tab2.amount is null

打破它: 找到每个日期和项目组的第二个最大时间。 将第二个最大时间与日期和项目上的原始table1结合起来,将得到的金额为上一个金额 使用此上一个金额根据日期和项目更新表2,只要new ='Y'

PS:我尚未在sql Developer上运行此查询。但是我使用的想法应该可行。

答案 3 :(得分:0)

您可以尝试...

    UPDATE T SET T.Amount = ( SELECT MAX(T2.Amount) FROM table2  T2 
    WHERE T2.Amount IS NOT NULL AND T2.[time] <= T.[time] and T2.item = T.item and t2.[date]=T.[date]
                      ) from table2  as T
      WHERE T.Amount IS NULL

标记它接受,如果可以的话。