【问题标题】:Oracle Query : Single update statementOracle 查询:单个更新语句
【发布时间】:2014-06-05 22:33:01
【问题描述】:

我需要为以下逻辑编写一个 Oracle 查询代码,不胜感激。

我有一个包含 8 列的表,其中需要为特定业务逻辑考虑 3 列。

表格数据(3列)

A               B             C 

071699          01            I

071699          01W     

071699          02W     

071699          01W           I

071699          02W     

更多行。

数据量因情况而异,这意味着每列 A-B 组合可能是一行或多行,通常不在这些行中 至少为 1 个组合填充了 C 列。

此表有超过 100K 的不同 A 值。

我需要实现的逻辑:

  1. 检查 - 对于特定的 A 值,我们有多少组合 (A-B)。 对于特定的 A:检查是否有任何组合 (A-B) 填充了 C 列数据。
  2. 从填充的 C 列中获取值并更新同一个表(对于相同 A 的其他组合)

之前的数据(只显示特定的行)

A               B             C 

071699          01            I

071699          01W     

071699          02W     

查询后的数据

A               B             C  

071699          01            I

071699          01W           I

071699          02W           I

我有一个 SQL 服务器查询在单个查询中执行此逻辑,但在 Oracle 中不起作用,我收到错误,“单行查询返回多行”

SQL 服务器查询

update c 
set c.colC = u.colC
from data_table u
join data_table c on u.colA = c.colA and u.colB <> c.colB
    and u.colB = (select MIN(colB) from data_table  
                    where colA = u.colA and colC is not    null)
and u.colC is not null and c.colC is null

感谢任何帮助编写类似的 oracle 版本。

【问题讨论】:

  • 查看UPDATE
  • 尝试将u.colB = (select 更改为u_colB IN (select
  • 感谢您的建议。我尝试使用“IN”并且查询不起作用并且仍然给我错误。对于另一个链接,它提供了非常通用的更新语句的语法,没有给出这个问题的任何细节。如果您能针对此问题提供任何建议,我将不胜感激。
  • 对于 A 列和 B 列的相同组合,C 列中是否可以有两个不同的值?如果是,您会采用哪个值来更新?
  • 不,情况并非如此,尽管它由具有统计和结束日期的其他列确定。假设是一样的,我们如何将这个 SQL server 查询转换成 oracle。

标签: oracle plsql


【解决方案1】:

Oracle 不允许在更新查询中进行联接,除非您有一个唯一的列来保证 1-1 映射,这绝对不适用于您的情况。因此,您可以在这里做的最好的事情是嵌套子查询。它不漂亮,但它会起作用。我无法将您说需要实现的逻辑与 SQL Server 更新语句中的逻辑完全匹配,所以我使用了该语句。

UPDATE data_table u
SET u.COLC =(
  SELECT  c.ColC
  FROM    data_table c
  WHERE   c.ColA = u.ColA
    and   c.ColB =(
        SELECT  MIN( ColB )
        FROM    data_table
        WHERE   ColA = c.ColA
          AND   ColC IS NOT NULL
      )
)
where u.ColC is null;

【讨论】:

  • 这在我的情况下不起作用,因为内部查询确实返回多行。
  • 是的,内部查询返回多行。但是,不起作用的更新是什么?我根据您提供的数据对其进行了测试。
  • 内部查询将返回多于一行,例如 - 这个表有大约 100k 个不同的 colA 并且对于每个 colA - 我们可以有多个 colB,所以对于 1 colA 我们可以有多个 colA-ColB组合,并且每个组合对于 colC 可以具有空值或特定值。在这种情况下 - 内部查询可能会给出多行输出,但如果我们将 colA-ColC 的不同组合放在单独的表中,然后在单独的语句中更新,那么它将适用于所有可能的情况。如果您有任何具体问题,请告诉我。
  • 我无法用您上面显示的示例数据来解决您现在所说的问题。您在 A 中具有相同值的三行,在 B 中具有所有不同的值。您将所需的结果显示为所有具有 NULL C 值的 A 值得到非 NULL C 值,而不管 B 值如何。
【解决方案2】:

我尝试了各种方法在单个查询中完成此任务,但由于 Oracle 限制而无法实现,以下是适合我的解决方案:

我将查询分为两部分 - 一个执行插入语句,另一个执行更新。

  1. 第一个查询:这里我将行插入到另一个临时表中,逻辑 - 为每个 colA 获取不同的行 - ColC 是 colC 被填充的地方。

  2. 使用步骤 1 中创建的 tmp 表,通过 colA 上的连接来更新主数据表。

如果有人有更好的解决方案,请发送您的回复,我一定会尝试。

【讨论】:

    【解决方案3】:

    在尝试了各种方法(例如拆分为两个 tmp 表、游标等)后,我用基于集合的编码解决了这个问题,下面是示例代码:

    此查询比任何其他解决方案快 3-5 倍。

       UPDATE data_table a SET C = (
            WITH comp AS (
            SELECT  DISTINCT A, C FROM data_table a 
            WHERE B = (SELECT MIN(B) FROM data_table
                                  WHERE A =  a.A
                                  AND C IS NOT NULL)
                        )
             SELECT 
                CASE
                    when a.C IS NULL  THEN c.C
                    when a.C IS NOT NULL THEN a.C
                END    
             FROM comp c 
             WHERE a.A = c.A AND c.C IS NOT NULL  
         );
    

    【讨论】:

      猜你喜欢
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多