【问题标题】:Update with group by使用分组更新
【发布时间】:2015-06-23 21:13:21
【问题描述】:

我对看似简单的 UPDATE 语句感到困惑。

我正在寻找一个使用两个值的更新。第一个 (a) 用于分组,第二个 (b) 用于找到相应组内的局部最小值。另外,在 b 上有一个阈值:任何 1 或更小的值都应保持原样。

drop table t1;
create table t1 (a number, b number);
insert into t1 values (1,0);
insert into t1 values (1,1);
insert into t1 values (2,1);
insert into t1 values (2,2);
insert into t1 values (3,1);
insert into t1 values (3,2);
insert into t1 values (3,3);
insert into t1 values (4,1);
insert into t1 values (4,3);
insert into t1 values (4,4);
insert into t1 values (4,5);


-- 1,0 -> 1,0
-- 1,1 -> 1,1
-- 2,1 -> 2,1
-- 2,2 -> 2,2
-- 3,1 -> 3,1
-- 3,2 -> 3,2
-- 3,3 -> 3,2  <-
-- 4,1 -> 4,1
-- 4,3 -> 4,3  <-
-- 4,4 -> 4,3  <-
-- 4,5 -> 4,3  <-

显然不够的是:

update t1 x
   set b = (select min(b) from t1 where b > 1)
;

无论我尝试什么更复杂的东西,例如

UPDATE t1 x
   set (a,b) = (select distinct a,b from (
                    select a, min(b) from t1 where b > 1 group by a)
               )
;

我明白了 SQL-Fehler: ORA-01427: Unterabfrage für eine Zeile liefert mehr als eine Zeile 01427. 00000 - “单行子查询返回多于一行”

这并不奇怪,因为我需要为 a 的每个值设置一行。

当然,我可以编写一个带有游标循环的 PL/SQL 过程,但它可以在一个优雅的 SQL 语句中实现吗?也许使用分区?

【问题讨论】:

    标签: oracle group-by partition


    【解决方案1】:

    你的问题有点混乱。 您说您想将值b 设置为分区a 中的最小值,该列b 所在行,而包含b = 1 的行应保持不变。

    根据我在您的问题中看到的 cmets(我假设这是您的预期输出),您还希望获得分区内 1 之后的最小值 - 所以您基本上想要 b 的最小值大于1

    下面是执行此操作的 SQL 查询

    UPDATE t1 alias
      SET b = (
        SELECT min(b) 
        FROM t1 
        WHERE alias.a = t1.a 
          AND t1.b > 1 -- this would get the minimum value higher than 1
        GROUP BY a
      )
      WHERE alias.b > 1 -- update will not affect rows with b <= 1
    

    更新后的输出

     a | b 
    ---+---
     1 | 0
     1 | 1
     2 | 1
     2 | 2
     3 | 1
     3 | 2
     3 | 2
     4 | 1
     4 | 3
     4 | 3
     4 | 3
    

    【讨论】:

    • 所以自联接就可以了。谢谢你,蒂姆,它可以按要求工作。 :)
    • 没错,在这种情况下,您需要引用要更新的表。如果答案对您有用,请考虑通过检查左侧的标记来接受它。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多