批量更新开始日期基于上一个结束日期

时间:2016-11-29 17:21:29

标签: sql oracle lag

我正在尝试对包含大约700K记录的表进行批量更新。我需要使用上一条记录的有效结束日期更新有效开始日期。使用子查询时,我在更新语句上遇到问题。即使使用日期过滤器也需要一个多小时才能运行(2016年7月1日至2016年6月15日,大约2k记录)。我在一个简单的更新语句,插入和循环中尝试了它。使用ROWID而不是account_dim_key(表上的PK)的解释计划更加优化,但是,我得到一个错误,即子查询返回多行。我不确定为什么ROWID会发生这种情况。

ID是表上的自然键,account_dim_key是PK且唯一。两者都被编入索引。表是2型SCD。

  1. 如何使用ROWID
  2. 修改更新语句
  3. 使用FORALL更新是否更优化?如果是这样,我将如何编写它(对pl sql是新的,对于数组是不可用的)
  4. 使用ROWID更新语句返回错误单行子查询返回多行但具有最佳解释计划

    UPDATE DEXWHS.D_ACCOUNT_VEEVA
       SET effective_end_dt =
              (SELECT prev_dt
                 FROM (SELECT LAG (
                                 effective_end_dt,
                                 1,
                                 effective_start_dt)
                              OVER (PARTITION BY account_dim_key
                                    ORDER BY effective_start_dt)
                                 AS prev_dt,
                              ROWID AS rid
                         FROM dexwhs.d_account_veeva ac2) a
                WHERE a.rid = ROWID)
    

    使用非最佳解释计划的acocunt_dim_key更新语句

    UPDATE DEXWHS.D_ACCOUNT_VEEVA
       SET effective_end_dt =
              (SELECT prev_dt
                 FROM (SELECT LAG (
                                 effective_end_dt,
                                 1,
                                 effective_start_dt)
                              OVER (PARTITION BY id
                                    ORDER BY effective_start_dt, account_dim_key)
                                 AS prev_dt,
                              account_dim_key AS rid
                         FROM dexwhs.d_account_veeva ac2) a
                WHERE a.rid = account_dim_key)
    

    使用循环更新

    CREATE OR REPLACE PROCEDURE PREV_UPDT
    IS
       CURSOR c1
       IS
            SELECT account_dim_key,
                   id,
                   active_flag,
                   effective_end_dt,
                   effective_start_dt,
                   created_date,
                   last_modified_date,
                   (SELECT prev_dt
                      FROM (SELECT LAG (
                                      effective_end_dt,
                                      1,
                                      effective_start_dt)
                                   OVER (
                                      PARTITION BY id
                                      ORDER BY effective_start_dt, account_dim_key)
                                      AS prev_dt,
                                   account_dim_key AS rid
                              FROM dexwhs.d_account_veeva ac2) a
                     WHERE a.rid = src.account_dim_key)
              FROM dexwhs.d_account_veeva src
          ORDER BY id, effective_start_dt, account_dim_key;
       r1   c1%ROWTYPE;
    BEGIN
       OPEN c1;
    
       LOOP
          FETCH c1 INTO r1;
    
          EXIT WHEN c1%NOTFOUND;
          DBMS_OUTPUT.PUT_LINE ('id=' || r1.id);
    
          UPDATE dexwhs.D_ACCOUNT_VEEVA trgt
             SET trgt.effective_start_dt = r1.prev_date,
                 trgt.audit_last_update_dt = SYSDATE,
           WHERE trgt.account_dim_key = r1.account_dim_key;
    
          DBMS_OUTPUT.PUT_LINE ('r1.id_found');
       END LOOP;
    
       CLOSE c1;
    END
    

1 个答案:

答案 0 :(得分:0)

如果var data1 = [ {month: 'Jan', A: 20, B: 5, C: 10}, {month: 'Feb', A: 30, B: 10, C: 20} ]; var data2 = [ {month: 'Mar', A: 10, B: 55, C: 100}, {month: 'Apr', A: 10, B: 70, C: 2} ]; var xData = ["A", "B", "C"]; var margin = {top: 20, right: 50, bottom: 30, left: 50}, width = 400 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; var x = d3.scale.ordinal() .rangeRoundBands([0, width], 0.35); var y = d3.scale.linear() .rangeRound([height, 0]); var color = d3.scale.category20(); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); function draw(data) { var dataIntermediate = xData.map(function (c) { return data.map(function (d) { return {x: d.month, y: d[c]}; }); }); var dataStackLayout = d3.layout.stack()(dataIntermediate); x.domain(dataStackLayout[0].map(function (d) { return d.x; })); y.domain([0, d3.max(dataStackLayout[dataStackLayout.length - 1], function (d) { return d.y0 + d.y;}) ]) .nice(); var layer = svg.selectAll(".stack") .data(dataStackLayout); layer.exit().remove(); // has no effect layer.enter().append("g") .attr("class", "stack") .style("fill", function (d, i) { return color(i); }); var rect = layer.selectAll("rect") .data(function (d) { return d; }); rect.exit().remove(); // has no effect rect.enter().append("rect") .attr("x", function (d) { return x(d.x); }) .attr("y", function (d) { return y(d.y + d.y0); }) .attr("height", function (d) { return y(d.y0) - y(d.y + d.y0); }) .attr("width", x.rangeBand()); svg.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "axis") .call(yAxis); } function updateData() { draw(data2); } d3.select('#update') .on("click", updateData); draw(data1); 是主键,请尝试account_dim_key

MERGE

查询必须花一些时间,因为它正在更新整个表格。

也许您可以使用MERGE INTO dexwhs.d_account_veeva a USING ( SELECT account_dim_key, LAG ( effective_end_dt, 1, effective_start_dt) OVER (PARTITION BY account_dim_key ORDER BY effective_start_dt) AS prev_dt FROM dexwhs.d_account_veeva ) b ON (a.account_dim_key = b.account_dim_key ) WHEN MATCHED THEN UPDATE SET a.effective_end_dt = b.prev_dt 列上的复合索引加快LAG ... (PARTITION BY account_dim_key ORDER BY effective_start_dt)部分。

(account_dim_key, effective_start_dt)

但是Oracle可以忽略这个索引并且更喜欢全表扫描,因为子查询是针对整个表的。