Sql 根据条件按顺序更新列

Sql 根据条件按顺序更新列,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我使用的是oracle 11g,我被困在这个问题上 我的表格结构如下 ╔═══════╦══════╦════════╗ ║ tm_id ║ flag ║ countr ║ ╠═══════╬══════╬════════╣ ║ 1 ║ 0 ║ null ║ ║ 2 ║ 0 ║ null ║ ║ 3 ║ 1 ║ null ║ ║ 4 ║ 0 ║ null ║ ╚═══════╩══════╩════════╝ Oracle

我使用的是oracle 11g,我被困在这个问题上

我的表格结构如下

╔═══════╦══════╦════════╗ ║ tm_id ║ flag ║ countr ║ ╠═══════╬══════╬════════╣ ║ 1 ║ 0 ║ null ║ ║ 2 ║ 0 ║ null ║ ║ 3 ║ 1 ║ null ║ ║ 4 ║ 0 ║ null ║ ╚═══════╩══════╩════════╝ Oracle 11g R2架构设置:

问题1:

:

编辑-解释

这里使用SUM是一个聚合函数,而不是通常使用的聚合函数

SUM( 1 - FLAG ) OVER ( ORDER BY tm_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
几乎从右到左:

按tm_id排序-按tm_id升序对行排序 然后,对于每一行: 考虑无界的前一行和当前行之间的所有行,即仅从最早的tMyID开始到当前行的行。 对于这些行,查找SUM 1-标志,即当标志为零时递增计数器,而不是当标志为1时递增计数器。 Oracle 11g R2架构设置:

问题1:

:

编辑-解释

这里使用SUM是一个聚合函数,而不是通常使用的聚合函数

SUM( 1 - FLAG ) OVER ( ORDER BY tm_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
几乎从右到左:

按tm_id排序-按tm_id升序对行排序 然后,对于每一行: 考虑无界的前一行和当前行之间的所有行,即仅从最早的tMyID开始到当前行的行。 对于这些行,查找SUM 1-标志,即当标志为零时递增计数器,而不是当标志为1时递增计数器。
要在更新中使用子查询:


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

您希望在更新中使用子查询:

如果您的表很大,您可能会发现合并更有效。

您应该使用游标。 从表中获取所有行。 根据案例条件逐个更新循环中的行。 在循环的最后一个declare变量中存储countr值。 如果flag=1,则在下一轮循环中使用此变量。

您应该使用游标。 从表中获取所有行。 根据案例条件逐个更新循环中的行。 在循环的最后一个declare变量中存储countr值。
如果flag=1,则在下一轮循环中使用此变量。

谢谢,这非常有效……我尝试用谷歌搜索你使用的东西,但你能给我一些上下文吗?我很难把它们放在一起,也无法理解你写的内容。@user1561770-添加了求和分析函数的解释。谢谢,这非常有效……我试着用谷歌搜索你使用的东西,但你能给我一些上下文吗?我很难将它们放在一起,也无法理解您所写的内容。@user1561770-添加的求和分析函数说明。
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
             )
/
SELECT * FROM test
| TM_ID | FLAG | COUNTR |
|-------|------|--------|
|     1 |    0 |      1 |
|     2 |    0 |      2 |
|     3 |    1 |      2 |
|     4 |    0 |      3 |
SUM( 1 - FLAG ) OVER ( ORDER BY tm_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
update calendar t
    set countr = (select count(*)
                  from calendar t2
                  where t2.tm_id <= t.tm_id and t2.flag = 0
                 );