使用WITH CLAUSE进行更新

时间:2016-02-27 05:45:07

标签: sql oracle sql-update common-table-expression

我看到了一些接近这个问题的答案,但我无法将其中的任何一个放入我的场景中。

我在pl / sql(oracle 11g)中有以下内容: (编辑:我清理了一下sql以使其正确)

  WITH t AS
(
  SELECT  case_nbr, 
          type_cd, 
          subtype_cd, 
          class_nbr,
          case_dt,
          SUM(fhits) fhits_sum, 
          COUNT(fhits) hit_count
    FROM  DDEL.MYCASE 
    GROUP BY case_nbr, 
             type_cd, 
             subtype_cd, 
             class_nbr, 
             case_dt            
   )
   SELECT ROUND(mc.fhits/t.fhits_sum * mc.qty ) new_qty , t.*, mc.fhits, mc.qty
   FROM t 
   JOIN   DDEL.MYCASE mc
     ON t.case_nbr = mc.case_nbr
     AND t.type_cd = mc.type_cd 
     AND t.subtype_cd =  mc.subtype_cd
     AND t.class_nbr = mc.class_nbr
     AND t.case_dt = mc.case_dt
   WHERE t.fhits_sum > 1000
   AND t.hit_count > 1
); 

结果给了我(我只是编号不相关的列以使其更合适):<​​/ p>

new_qty  1  2   3  4  5             6   fhits  qty
57  10  E   S  8  01-DEC-15 133 2   999 77
20  10  E   S  8  01-DEC-15 133 2   934 77

这可以找到......但是,我想要做的是更新此查询的结果......在这种情况下是两条记录。我想用new_qty修改mc.qty列(你看到77的列)(你看到57和20)。

我无法使用WITH子句和此结果集进行更新。我想我必须做一些更复杂的事情,但希望有人能看到一个简单的方法来在这里添加UPDATE。请记住,查询在一个包含大量数据的表中查找一组不同的记录,这些记录不止一次匹配且满足条件,并且fhits列的总和超过1000值......只有这样我才能做到这一点。

在过去一天半的时间里,我一直在看这个问题太久了,而且我错过了一些明显的东西。谢谢你的帮助

2 个答案:

答案 0 :(得分:1)

我想知道您为什么使用LEFT OUTER JOIN来合并来自MYCASE mc的行和来自t的聚合结果?
这意味着case_nbr, type_cd, subtype_cd, class_nbr, case_dtt中可能存在值MYCASE mc的组合MYCASE ...但由于这些值来自... AND (t.colX = m.colX OR t.colX IS NULL AND m.colX IS NULL) ...表,因此坦率地说是不可能的,除非这些列中的某些列可以包含(并包含)NULL值 但在后一种情况下(连接列可以包含NULL),查询中的连接条件存在缺陷,因为不考虑NULL。 在这种情况下,连接条件必须包含:AND t.colX = m.colX而不是简单 SELECT mc.qty, ROUND(mc.qty * mc.fhits/t.fhits_sum) new_qty FROM ( SELECT case_nbr, type_cd, subtype_cd, class_nbr, case_dt, SUM(fhits) fhits_sum, COUNT(fhits) hit_count FROM MYCASE GROUP BY case_nbr, type_cd, subtype_cd, class_nbr, case_dt ) t JOIN MYCASE mc ON ( mc.case_nbr = t.case_nbr AND mc.type_cd = t.type_cd AND mc.subtype_cd = t.subtype_cd AND mc.class_nbr = t.class_nbr AND mc.case_dt = t.case_dt ) WHERE t.fhits_sum > 1000 AND t.hit_count > 1

无论如何,我们将使用新值更新qty列 假设连接条件中涉及的所有列都不能包含NULL,那么您的查询可以使用直接连接以这种方式重新编写:

qty

上述查询只提供两列:MYCASE来自new_qty表,而qty是一个新值UPDATE ( the_above_query_as_inline_view ) SET qty = new_qty; 必须更新。

您所需要的只是更新使用上述查询创建的内联视图:

UPDATE (
      SELECT mc.qty,
             ROUND(mc.qty * mc.fhits/t.fhits_sum) new_qty 
      FROM (
          SELECT case_nbr, type_cd, subtype_cd, class_nbr, case_dt,
                 SUM(fhits) fhits_sum, COUNT(fhits) hit_count
          FROM MYCASE 
          GROUP BY case_nbr, type_cd, subtype_cd, class_nbr, case_dt
      ) t
      JOIN MYCASE mc ON (
         mc.case_nbr = t.case_nbr AND mc.type_cd = t.type_cd
         AND mc.subtype_cd = t.subtype_cd AND mc.class_nbr = t.class_nbr
         AND mc.case_dt = t.case_dt
      )
      WHERE t.fhits_sum > 1000
       AND t.hit_count > 1
)
SET qty = new_qty;

即:

DISTINCT

补充说明:第一个子查询中的 SELECT DISTINCT case_nbr, type_cd, subtype_cd, class_nbr, case_dt, SUM(fhits) fhits_sum, COUNT(fhits) hit_count FROM DDEL.MYCASE GROUP BY case_nbr, type_cd, subtype_cd, class_nbr, case_dt 子句是多余的:

GROUB BY

如果使用DISTINCT和聚合,则结果始终是唯一的,无需添加SELECT DISTINCT a,b,c,d FROM table

此查询:SELECT a,b,c,d FROM table GROUP BY a,b,c,d 与以下内容等效:

{{1}}

答案 1 :(得分:-1)

MERGE命令将是正确的答案。 这也是最好的做法。