简体   繁体   English

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

[英]SQL: Use value from previous row to populate current row

I have two tables table1 and table2 like so. 我有两个表table1和table2像这样。 You can see the times have gaps 你可以看到时间有差距

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

I also have table2 where I fill the gaps 我也有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

The gap row for amount should take the value of the last/previous time. 金额的缺口行应采用上一次/上一次的值。 I was able to identify the missing rows and add the gap rows but I tried copying the amounts to the gap rows but was not successful. 我能够识别缺失的行并添加间隙行但我尝试将金额复制到间隙行但是没有成功。 I looked at what I thought were similar questions in stackoverflow and tried the solutions but it did not work such as: 我在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     

Does anyone know how to access the amount for the previous row? 有谁知道如何访问前一行的金额? A cursor works but that is a last resort solution. 游标可以工作,但这是最后的解决方案。 Thank you for taking the time from your busy day to help. 感谢您在忙碌的一天中抽出时间来帮忙。

adding my create table code 添加我的创建表代码

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

You need to find the previous non null value of amount : 您需要找到以前的非空值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'

See the demo . 演示

you should use windowing queries: 你应该使用窗口查询:

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

Maybe this Oracle solution will be helpful (I hope, that sql-server has something like rownum or similar solution). 也许这个Oracle解决方案会有所帮助(我希望,sql-server有类似rownum或类似的解决方案)。 First, order your data and get an unique numbers (rownum pseudocolumn used). 首先,订购您的数据并获得一个唯一的数字(使用rownum伪列)。 Second, for each number calculate maximal previous number witch non empty value. 其次,对于每个数字计算最大前一个数字非空值。 Join data. 加入数据。

Maybe there is a solution with analytical function, but no i don't have one in mind. 也许有一个具有分析功能的解决方案,但不,我没有想到的。

-- create test data
drop table tab1;
create table tab1 (
    ym varchar2(7),
    val number
);
insert into tab1 values('2016/01',3);
insert into tab1 values('2016/04',6);
insert into tab1 values('2016/08',4);
insert into tab1 values('2016/09',2);
insert into tab1 values('2016/01',5);
insert into tab1 values('2016/09',8);
insert into tab1 values('2016/05',7);
insert into tab1 values('2016/12',3);
insert into tab1(ym) values('2016/03');
insert into tab1(ym) values('2016/11');
insert into tab1(ym) values('2016/12');
insert into tab1(ym) values('2016/12');

-- solution
with q0 as (-- get rownum for each row
    select a.*, rownum as rnm -- get rownums
    from (
        select *
        from tab1
        order by ym -- order by, to further get proper order numbers from rownum
    ) a
),

q1 as (-- for each rnm get previous (maximal) rnm with non missing value
    select a.rnm, max(b.rnm) as rnm_prev
    from q0 a
    left join q0 b on a.rnm > b.rnm and b.val is not null -- get only smaller rnms with values
    group by a.rnm
)


select q0.ym, q0.rnm, q1.rnm_prev,
q0.val, pv.val as val_prev, nvl(q0.val, pv.val) as val_cor
from q0
left join q1 on q0.rnm = q1.rnm
left join q0 pv on q1.rnm_prev = pv.rnm
order by q0.rnm
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

Breaking it down: Find the 2nd max time for each Group of Date and item. 分解:找到每组日期和项目的第二个最长时间。 Join 2nd max time with the original table1 on Date and item to get the amount which will be prev Amount Use this prev amount to update table 2 based on Date and item wherever new ='Y' 在日期和项目上加入原始table1的第二个最长时间以获得将是prev的金额金额使用此prev金额根据日期和项目更新表2,无论new ='Y'

PS: I have not run this query on sql developer. PS:我没有在sql developer上运行此查询。 But the idea I've used should work. 但我用过的想法应该有效。

You may try this... 你可以尝试这个......

    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

mark it accepted if works fine. 如果工作正常,请接受标记。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从上一行减去当前行,保持上一行值不变 — SQL - Subtract current row from previous row, keeping previous row value as constant — SQL 在SQL(Postgres)中将前一行值动态添加到当前行值 - Dynamically add previous row value to current row value in SQL(Postgres) SQL。 比较当前行的值与前一行的相同比较结果的值 - SQL. Comparing value from current row versus the value resulted from the same comparison of the previous row SQL查询,用于将当前行值与先前的行值合并 - SQL query for concatinating current row value with previous row values Oracle PL / SQL:访问当前行中的上一行计算值 - Oracle PL/SQL : Accessing previous row calculated value in current row 在 SQL 的循环中将当前行值与前一行值进行比较 - Compare current row value with previous row values in loop in SQL 前一行列的值之和+当前行的值 - Sum of values from previous row columns + value of current row 使用上一行SQL Server更新当前行 - Update current row with previous row sql server 在SQL中减去上一行减去当前行 - Subtracting previous row minus current row in SQL 通过从 SQL 服务器中的当前行值中减去先前的运行总计来调整列值 - Adjusting a column value by subtracting previous running total from current row value in SQL Server
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM