根据即将到来的行中存在的值更新行

时间:2014-02-20 07:36:56

标签: sql oracle oracle11g oracle10g

我有一张包含以下数据的表格

-------------------
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语句。

3 个答案:

答案 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)

SQLFiddle