Oracle优化拆分行

时间:2012-09-27 11:57:35

标签: database oracle plsql

我有两个表数量(用户,年份,数量)和MonthlyQuantity(用户,年,月,数量) - 每月一个表是空的。 我需要做的是根据年度表填写每月表,将年度数量除以12个相等的部分,并在上个月添加任何休息。所以基本上,Quantity中的每一行都应该在QuantityMonthly中创建12行。 这是我怎么做的 - 问题是循环非常慢。

我怎么能更快地完成它?

    create ro replace 
procedure pr_test
AS
BEGIN
    FOR r IN (SELECT * FROM Quantity) LOOP

    DELETE FROM QuantityMonthly qm WHERE qm.company = r.company AND qm.year = r.year;

    INSERT ALL
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 1, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 2, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 3, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 4, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 5, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 6, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 7, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 8, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 9, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 10, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 11, trunc(r.quantity / 12))
    INTO QuantityMonthly (company, year, mon, qty) values (r.company, r.year, 12, trunc(r.quantity / 12) + mod(r.quantity , 12))
  SELECT * FROM dual;

END LOOP;

COMMIT;

END pr_test;

1 个答案:

答案 0 :(得分:1)

使用single statement,单集操作通常比许多小操作快得多:

MERGE INTO QuantityMonthly qm
 USING (SELECT *
          FROM Quantity q
         CROSS JOIN (SELECT rownum mon
                       FROM dual
                    CONNECT BY level <= 12)) q
    ON (qm.company = q.company
        AND qm.year = q.year
        AND qm.mon = q.mon)
WHEN MATCHED THEN
   UPDATE SET qm.quantity = q.quantity / 12 
                            + CASE WHEN q.mon = 12 THEN 
                                 mod(r.quantity, 12) 
                              ELSE 
                                 0 
                              END
WHEN NOT MATCHED THEN
   INSERT (company, year, mon, qty)
   VALUES (q.company, q.year, q.mon,
           q.quantity / 12 
           + CASE WHEN q.mon = 12 THEN mod(r.quantity, 12) ELSE 0 END);