根据条件顺序更新列

Sri*_*yer 0 sql oracle oracle11g

我正在使用oracle 11g而且我遇到了这个问题.

我的表结构如下

 
?????????????????????????
? tm_id ? flag ? countr ?
?????????????????????????
? 1     ? 0    ? null   ?
? 2     ? 0    ? null   ?
? 3     ? 1    ? null   ?
? 4     ? 0    ? null   ?
?????????????????????????

我想用一个顺序值更新列countr的所有值,如下所示

 
?????????????????????????
? tm_id ? flag ? countr ?
?????????????????????????
? 1     ? 0    ? 1      ?
? 2     ? 0    ? 2      ?
? 3     ? 1    ? 2      ?
? 4     ? 0    ? 3      ?
?????????????????????????

所以基本上,countr的值只应在标志为0时增加.如果为1则则不应增加(或者它应该具有先前的值)

我尝试了以下更新声明

UPDATE calendar 
SET countr = case when flag = 0 then  tm_id  else  countr-1 end
Run Code Online (Sandbox Code Playgroud)

MT0*_*MT0 5

SQL小提琴

Oracle 11g R2架构设置:

CREATE TABLE test ( tm_id, flag, countr ) AS
          SELECT 1,0, CAST( NULL AS NUMBER ) FROM DUAL
UNION ALL SELECT 2,0, CAST( NULL AS NUMBER ) FROM DUAL
UNION ALL SELECT 3,1, CAST( NULL AS NUMBER ) FROM DUAL
UNION ALL SELECT 4,0, CAST( NULL AS NUMBER ) FROM DUAL
/

UPDATE test t
SET countr = ( SELECT total
               FROM   (
                        SELECT tm_id,
                               SUM( 1 - FLAG ) OVER ( ORDER BY tm_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS total
                        FROM   test
                      ) x
               WHERE  t.tm_id = x.tm_id
             )
/
Run Code Online (Sandbox Code Playgroud)

查询1:

SELECT * FROM test
Run Code Online (Sandbox Code Playgroud)

结果:

| TM_ID | FLAG | COUNTR |
|-------|------|--------|
|     1 |    0 |      1 |
|     2 |    0 |      2 |
|     3 |    1 |      2 |
|     4 |    0 |      3 |
Run Code Online (Sandbox Code Playgroud)

编辑 - 说明

SUM这里的使用是作为分析函数而不是通常使用的聚合函数.

SUM( 1 - FLAG ) OVER ( ORDER BY tm_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
Run Code Online (Sandbox Code Playgroud)

从(几乎)从右到左:

  • ORDER BY tm_id- 按升序排序 tm_id
  • 然后为每一行:
    • 考虑所有ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(即只从最早tm_id到当前行的行)
    • 对于那些行找到SUM( 1 - FLAG )(即当标志为零时递增计数器而不是当它为1时).