【问题标题】:How to use an outer query variable in a nested sub query using update如何使用更新在嵌套子查询中使用外部查询变量
【发布时间】:2020-09-19 10:51:34
【问题描述】:

我正在使用一个更新查询,其中我在嵌套子查询中使用了一个外部变量,但我发现一个错误:

SQL 错误:ORA-00904:“FS”。“GR_NUMBER”:标识符无效

update table fs set fs.branch_id=
(select branch_id
from
    (select  branch_id,row_number() over(PARTITION by gr_number order by updated_ts desc) as Sno
from admission_log
where gr_number=fs.gr_number )
where sno=1) ;

【问题讨论】:

  • 表FS是否有列名GR_NUMBER?您的查询对我来说似乎很好。请提供DESC FS的输出
  • 是的表 fs 有列 GR_NUMBER
  • 我修改我的问题请看这个错误..
  • 我已将此问题回滚到其早期版本。不应使用已给出答案的新版本修改问题,因为这会使现有答案无效。 请针对您的新问题提出一个新问题

标签: sql oracle oracle11g sql-update


【解决方案1】:

您的查询的问题是您试图访问下两层的子查询中的fs.gr_number 列。您只能访问下一级子查询中的顶级列。

你的陈述应该是:

UPDATE fs
SET    fs.branch_id = (SELECT branch_id
                       FROM   (SELECT branch_id,
                                      gr_number,
                                      row_number() OVER (PARTITION BY gr_number ORDER BY updated_ts DESC) AS sno
                               FROM   admission_log) x
                       WHERE  x.gr_number = fs.gr_number
                       AND    sno = 1);

这会将相关性降低到一个级别。请注意我是如何给嵌套子查询起别名的。

性能应该不会很糟糕,因为x.gr_number = fs.gr_number 谓词涉及子查询中分析函数正在分区的同一列。这应该允许 Oracle 适当地过滤子查询。


ETA:您也可以改用 MERGE 语句:

MERGE INTO fs tgt
  USING (SELECT branch_id,
                row_number() OVER (PARTITION BY gr_number ORDER BY updated_ts DESC) AS sno
         FROM   admission_log) src
    ON (tgt.gr_number = src.gr_number AND src.sno = 1)
WHEN MATCHED THEN
  UPDATE tgt.branch_id = src.branch_id;

【讨论】:

  • (我已将问题回滚,并已要求问题作者发布新问题)。
【解决方案2】:

由于是Oracle,所以可以使用merge子句,使用min()函数代替row_number()函数获取值。

merge into table fs using
(select gr_number, min(branch_id) as branch_id from admission_log) qry
on
(fx.gr_number = qry.gr_number)
when matched then
update
set
fs.branch_id = qry.branch_id;

如果你还想使用 roe_number() 函数,下面是查询。加入表的 WHERE 子句应该在子查询之外。

update table fs set fs.branch_id=
(select branch_id
from
(select  branch_id,row_number() over(PARTITION by gr_number order by updated_ts desc)
as Sno
from admission_log)
where sno=1
and gr_number=fs.gr_number) ;

【讨论】:

  • min(branch_id) 不一定会给出正确的结果。
  • 为什么不呢,你取的是 rownum = 1,这里是 min(branch_id)。它有什么不同?根据 min(branch_id) 对 gr_number 进行分组将提供与采用 rownum = 1 相同的结果。如果他想采用第 1 行编号以外的其他内容,则 min(branch_id) 没有意义
  • 解析函数是根据最新的 updated_ts 值查找最新的 branch_id。如果最新行的 branch_id 为 10,但较早的行有 5,则您的 min(branch_id) 将返回错误值。
  • (我已将问题回滚,并已要求问题作者发布新问题)。
【解决方案3】:

使用此代码:

update fs a
set a.branch_id =
   (select c.branch_id
      from (select b.branch_id,
                   row_number() over(PARTITION by b.gr_number order by b.updated_ts desc) as Sno
              from admission_log b
             where b.gr_number = a.gr_number) c
     where c.sno = 1);

【讨论】:

    猜你喜欢
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多