SQL:使用前一行中的值填充当前行
我有两张桌子,一张桌子和二张桌子一样。你可以看到时间有差距SQL:使用前一行中的值填充当前行,sql,sql-server,join,Sql,Sql Server,Join,我有两张桌子,一张桌子和二张桌子一样。你可以看到时间有差距 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
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
我还有表2,我在其中填补了空白
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
您应该使用窗口查询:
select
*,sum(amount) over (partition by time order by time) as previous_amount_for_null_values
from table2
也许这个Oracle解决方案会有所帮助,我希望sql server有类似rownum或类似的解决方案。首先,对数据进行排序,并使用唯一的numbers rownum伪列。第二,对于每个数字,计算非空值的最大前一个数字。连接数据 也许有一个解析函数的解,但不,我脑子里没有
-- 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
细分:
查找每组日期和项目的第二个最长时间。
将第二个最大时间与日期和项目的原始表1连接,以获得上一个金额
使用此上一个金额根据日期和项目更新表2,只要是新的='Y'
PS:我还没有在SQLDeveloper上运行这个查询。但是我使用的想法应该有效。您需要找到前面的非空值amount: 请参阅。您可以试试这个
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
如果工作正常,请将其标记为已接受。这不起作用,我没有使用运行总数,只是直接复制。有人有其他建议吗?谢谢。此表2是根据您的查询创建的。是的,我有原始的表1,然后我创建了一个新的表2,填补了空白。我希望看到用于错误检查的表的不同版本。请共享您的查询以创建表2…既然您已经用tab1和gaps中的值填充了tab2,为什么您要加入tab1以尝试获取值以填补空白?所需的值已经存在于tab2中,或者我缺少simething?这就是我所做的。我在问题中发布了我的代码,但sql server不喜欢我的查询。非常感谢,这是有效的,但是我必须在第二个select语句中添加和time
-- 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
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'
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