Курсор для запроса запроса - PullRequest
0 голосов
/ 17 июня 2020

Я вставляю в TABLE_A, как указано ниже.

INSERT 
       INTO Table_A (house_id,
                    house_key_nbr,
                    mnty_code,
                    split) 
     SELECT wcp.id,
            ld.ld_ln_id, 
            ld.ld_mnty,           
            ROUND((ld.ld_ln_bal/wla.LOAN_AMT) * 100,2) split
       FROM table_B ld,
                 table_C cc,
                 TABLE_D wcp, 
                 TABLE_E wla    
      WHERE cc.conv_id         = I_conv_id
        AND cc.ev_id           = wcp.ev_id 
        AND cc.client_plan_nbr = ld.plan_id
        AND wcp.ssn            = ld.ssn
        AND wla.house_id        = wcp.id
        AND wla.house_key_nbr  = ld.ld_ln_id
        AND ld.status_code in ('V','W');
     

После того, как я загрузился в table_A, я создал курсор, чтобы найти записи, сумма разбиения которых не равна 100. Для тех случаях я найду разницу, а затем обновлю запись, как указано ниже.

CURSOR max_percent IS                                                     
   SELECT house_id,                                                           
          house_key_nbr,                                                     
          sum(split) percent_sum                                     
     FROM TABLE_A s1,                             
          TABLE_D p1,                                            
          table_C c1                                               
    WHERE s1.house_id = p1.id                                           
      AND p1.ev_id = c1.ev_id                                            
      AND c1.conv_id = I_conv_id                                       
    GROUP BY house_id, house_key_nbr                                    
   HAVING SUM(split) != 100;         
         
     OPEN max_percent;

     l_debug_msg:='Cursor Opened';
     
     FETCH max_percent BULK COLLECT INTO mnty_rec;  
     
     l_debug_msg:='Fetching the values from cursor';
     
     FOR i    IN 1..mnty_rec.COUNT
     LOOP
         v_diff := 100.00 - mnty_rec(i).percent_sum; 
         l_debug_msg:='The difference is '||v_diff||' for the house_id : '||mnty_rec(i).house_id;

         UPDATE work_conv_part_loan_mnty_splt wcplms       
            SET split        = split + v_diff       
          WHERE wcplms.house_id       = mnty_rec(i).house_id                 
            AND wcplms.house_key_nbr = mnty_rec(i).house_key_nbr              
            AND rownum = 1;  

         l_debug_msg:='Updated the percentage value for the house_id'||mnty_rec(i).house_id ; 
     END LOOP;
     CLOSE max_percent;
     

Вопрос в том, что я выполнил этот простой процесс с помощью курсора. Есть ли способ добиться этого во время самой вставки вместо того, чтобы писать курсор?

Ответы [ 2 ]

1 голос
/ 17 июня 2020

Если mnty_code уникален для каждой пары house_id, house_key_nbr, то вы можете использовать оконные функции в своей вставке. Попробуйте использовать это для вставки в столбец split:

        CASE WHEN 1 = ROWNUMBER() OVER ( PARTITION BY wcp.id, ld.ld_ln_id ORDER BY mnty_code DESC ) THEN
          -- This is the last row for the given house_id / house_key_nbr, so do special split calculation
          100 - SUM(ROUND((ld.ld_ln_bal/wla.LOAN_AMT) * 100,2)) OVER ( PARTITION BY wcp.id, ld.ld_ln_id ORDER BY mnty_code ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) ELSE
         -- Normal split calculation
           ROUND((ld.ld_ln_bal/wla.LOAN_AMT) * 100,2) 
           END split

Идея состоит в том, что если вы вставляете последнюю строку для заданного house_id, house_key_nbr, тогда установите split значение 100 минус сумма всех предыдущих значений.

Если mnty_code не является уникальным в каждой паре house_id, house_key_nbr, возникает проблема c, потому что нет возможности идентифицировать «последняя» строка в каждой группе.

1 голос
/ 17 июня 2020

Я немного упрощаю вашу настройку двумя таблицами: table_a накопление данных и table_b, содержащее новые данные.

-- TABLE_A: Primary Key  HOUSE_ID, HOUSE_KEY_NBR
create table table_a as
select 1 house_id, 1 house_key_nbr, 90 split from dual union all
select 1 house_id, 2 house_key_nbr, 30 split from dual union all
select 1 house_id, 3 house_key_nbr, 100 split from dual;

-- TABLE_B: new data
create table table_b as
select 1 house_id, 1 house_key_nbr, 5 split from dual union all
select 1 house_id, 1 house_key_nbr, 5 split from dual union all
select 1 house_id, 4 house_key_nbr, 50 split from dual union all
select 1 house_id, 4 house_key_nbr, 40 split from dual union all
select 1 house_id, 5 house_key_nbr, 100 split from dual;

Важным моментом является то, что table_a имеет первичный определен ключ, поэтому вам нужно обновить только одну строку для исправления SPLIT

Первый шаг прост: MERGE новые данные

MERGE INTO table_a a
USING (select HOUSE_ID, HOUSE_KEY_NBR, sum(SPLIT) SPLIT
       from table_b
       group by HOUSE_ID, HOUSE_KEY_NBR) b
ON (a.HOUSE_ID = b.HOUSE_ID and a.HOUSE_KEY_NBR = b.HOUSE_KEY_NBR)
WHEN MATCHED THEN 
  update SET a.SPLIT = a.SPLIT + b.SPLIT
WHEN NOT MATCHED THEN
  insert (HOUSE_ID, HOUSE_KEY_NBR, SPLIT)
  values (b.HOUSE_ID, b.HOUSE_KEY_NBR, b.SPLIT)

Итак, в основном вы сначала агрегирует новые данные до уровня PK, а затем с помощью MERGE либо вставляет, либо обновляет table_a

. На втором этапе выполните исправление, используя тот же подход с MERGE, только используйте другой исходная таблица, содержащая только отклонение SPLIT от 100.

MERGE INTO table_a a
USING (select HOUSE_ID, HOUSE_KEY_NBR, 100 - sum(SPLIT)  SPLIT
       from table_a
       group by HOUSE_ID, HOUSE_KEY_NBR 
       having sum(SPLIT) != 100) b
ON (a.HOUSE_ID = b.HOUSE_ID and a.HOUSE_KEY_NBR = b.HOUSE_KEY_NBR)
WHEN MATCHED THEN 
  update SET a.SPLIT = a.SPLIT + b.SPLIT
WHEN NOT MATCHED THEN
  insert (HOUSE_ID, HOUSE_KEY_NBR, SPLIT)
  values (b.HOUSE_ID, b.HOUSE_KEY_NBR, b.SPLIT)

После этого шага все SPLIT равны 100

select HOUSE_ID, HOUSE_KEY_NBR,   sum(SPLIT)
from table_a
group by HOUSE_ID, HOUSE_KEY_NBR
order by 1,2;

  HOUSE_ID HOUSE_KEY_NBR SUM(SPLIT)
---------- ------------- ----------
         1             1        100
         1             2        100
         1             3        100
         1             4        100
         1             5        100

Если вы не хотите MERGE в table_a, а вы используете только INSERT, я бы бросил вызов этому дизайну, потому что неясно, какую из многих записей с тем же ключом вы хотите обновить.

Я рекомендую не UPDATE но до INSERT дополнительных строк с исчислением лат. разница SPLIT.

...