根据条件

时间:2015-06-15 12:32:15

标签: 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      ║
╚═══════╩══════╩════════╝

所以基本上,只有当标志为0时,countr的值才会增加。如果为1,那么它不应该增加(或者它应该有前一个值)

我尝试了以下更新声明

UPDATE calendar 
SET countr = case when flag = 0 then  tm_id  else  countr-1 end

3 个答案:

答案 0 :(得分:5)

SQL Fiddle

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
             )
/

查询1

SELECT * FROM test

<强> Results

| TM_ID | FLAG | COUNTR |
|-------|------|--------|
|     1 |    0 |      1 |
|     2 |    0 |      2 |
|     3 |    1 |      2 |
|     4 |    0 |      3 |

编辑 - 说明

此处SUM的使用与analytic function相同,而不是通常使用的聚合函数。

SUM( 1 - FLAG ) OVER ( ORDER BY tm_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )

从(几乎)从右到左:

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

答案 1 :(得分:1)

您想在update中使用子查询:

update calendar t
    set countr = (select count(*)
                  from calendar t2
                  where t2.tm_id <= t.tm_id and t2.flag = 0
                 );

如果您的表格很大,您可能会发现merge效率更高。

答案 2 :(得分:0)

你应该使用光标。 从表中获取所有行。 基于案例条件在循环基础上逐个更新。 将countr值存储在循环的最后一个声明变量中。 如果flag = 1,则在下一轮循环中使用此变量。