2015-06-15 86 views
0

我在oracle 11g上,我被困在這個問題上。根據條件依次更新一列

我的表結構如下

 
╔═══════╦══════╦════════╗ 
║ tm_id ║ flag ║ countr ║ 
╠═══════╬══════╬════════╣ 
║ 1  ║ 0 ║ null ║ 
║ 2  ║ 0 ║ null ║ 
║ 3  ║ 1 ║ null ║ 
║ 4  ║ 0 ║ null ║ 
╚═══════╩══════╩════════╝

我想用一個連續的值,如下

 
╔═══════╦══════╦════════╗ 
║ tm_id ║ flag ║ countr ║ 
╠═══════╬══════╬════════╣ 
║ 1  ║ 0 ║ 1  ║ 
║ 2  ║ 0 ║ 2  ║ 
║ 3  ║ 1 ║ 2  ║ 
║ 4  ║ 0 ║ 3  ║ 
╚═══════╩══════╩════════╝

更新列COUNTR的所有值,所以基本上是COUNTR值只能增加,如果該標誌是0.如果它是1那麼它不應該增加(或它應該有以前的值)

我試過以下更新語句

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

回答

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時遞增計數器)。
+0

感謝這工作完美...我嘗試了你使用的東西的谷歌搜索,但你能給我一些上下文嗎?我很難將它們放在一起,並理解你寫的內容。 –

+0

@ user1561770 - 添加了「SUM」分析功能的說明。 – MT0

1

要在update使用子查詢:

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

如果你的表是大,你可能會發現,merge更有效。

0

您應該使用光標。 從表中獲取所有行。 根據案例條件循環更新一行。 將countr值存儲在循環的最後一個聲明變量中。 如果flag = 1,則在下一個循環中使用此變量。