我有一张包含以下数据的表格
-------------------
ID Key Value
-------------------
1 1
2 0
3 1
4 0
5 0
6 0
7 1
8 0
9 0
--------------------
我想更新Value
列,如下所示
-------------------
ID Key Value
-------------------
1 1 0
2 0 1
3 1 0
4 0 3
5 0 2
6 0 1
7 1 0
8 0 0
9 0 0
--------------------
也就是说,每个Key
= 1将Value
= 0.每个Key
= 0将Value
=从当前行到行的遍历数有Key
= 1。最后两个Key
,因为没有'1'可以跟随,Value
= 0。
我需要一个简单的Oracle SQL Update语句。
答案 0 :(得分:5)
SQL> create table t (id int, key int, value int);
SQL> insert into t (id, key)
2 select * from
3 (
4 select 1 x, 1 y from dual union all
5 select 2, 0 from dual union all
6 select 3, 1 from dual union all
7 select 4, 0 from dual union all
8 select 5, 0 from dual union all
9 select 6, 0 from dual union all
10 select 7, 1 from dual union all
11 select 8, 0 from dual union all
12 select 9, 0 from dual
13 )
14 /
Создано строк: 9.
SQL> commit;
SQL> select * from t;
ID KEY VALUE
---- ---------- ----------
1 1
2 0
3 1
4 0
5 0
6 0
7 1
8 0
9 0
SQL> merge into t using(
2 select id, key,
3 decode(key,1,0,
4 decode((max(key) over(order by id rows between current row and unbounded following)),0,0,
5 sum(decode(key,0,1)) over(partition by grp order by id rows between current row and unbounded following))
6 )
7 value
8 from (
9 select id, key, decode(key,1,0,
10 decode((max(key) over(order by id rows between current row and unbounded following)),0,0, -- Define if there is 1 below
11 (sum(key) over(order by id rows between current row and unbounded following))
12 )) grp
13 from t
14 )
15 ) src
16 on (t.id = src.id)
17 when matched then
18 update set t.value = src.value
19 /
SQL> select * from t;
ID KEY VALUE
---- ---------- ----------
1 1 0
2 0 1
3 1 0
4 0 3
5 0 2
6 0 1
7 1 0
8 0 0
9 0 0
答案 1 :(得分:4)
如果ID字段中没有间隙,则此查询将执行此操作:
UPDATE TEST_T tm
SET VALUE = (SELECT CASE WHEN t1.KEY = 1 THEN 0
WHEN (SELECT MIN(ID) FROM TEST_T t2
WHERE t2.ID > t1.id
AND t2.key = 1) IS NOT NULL
THEN (SELECT MIN(ID) FROM TEST_T t2
WHERE t2.ID > t1.id
AND t2.key = 1) - t1.id
ELSE 0
END VALUE
FROM TEST_T t1
WHERE t1.id = tm.id)
答案 2 :(得分:4)
试试这个:
UPDATE app
SET val =
CASE
WHEN app.fl_key = 1 THEN 0
ELSE
(SELECT COUNT(*) FROM app a2
WHERE a2.id >= app.id
AND a2.fl_key = 0
AND a2.id <
(SELECT MIN(a3.id) FROM app a3
WHERE a3.fl_key = 1
AND a3.id > app.id)
)
END
我重命名了你的字段:key为fl_key,value为val,因为在我的DBMS测试中是保留关键字。
我试着解释我的解决方案:
如果fl_key = 1很简单,我将val字段设置为0(如你所愿)
否则
我计算所有id,fl_key = 0小于min id,fl key = 1但是比我当前的id(app.id)