我在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
答案 0 :(得分:5)
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,则在下一轮循环中使用此变量。