简体   繁体   中英

Merge multiple rows into one?

I have one stage table ' STAGE_TABLE ' which includes following values (columns are varchar2 except ids) -

+-------------------------------------------------------------------------------------------------------------------------
¦  STAGE_ID ¦ EMP_ID     ¦ ATTR1_OLD_VAL ¦ ATTR1_NEW_VAL ¦ ATTR2_OLD_VAL ¦ ATTR2_NEW_VAL ¦ ATTR3_OLD_VAL ¦ ATTR3_NEW_VAL ¦
¦-----------+------------+---------------+---------------+---------------+---------------+---------------+---------------¦
¦         1 ¦       E001 ¦ xyz           ¦ pqr           ¦ mmm           ¦ nnn           ¦ zzz           ¦ aaa           ¦
¦         2 ¦       E001 ¦               ¦               ¦               ¦               ¦               ¦               ¦
¦         3 ¦       E001 ¦ pqr           ¦ abc           ¦ xxx           ¦ yyy           ¦               ¦               ¦
¦         4 ¦       E002 ¦ aaa           ¦ ccc           ¦ bbb           ¦ ttt           ¦               ¦               ¦
¦         5 ¦       E002 ¦               ¦               ¦               ¦               ¦ fff           ¦ ppp           ¦
¦         6 ¦       E002 ¦               ¦               ¦ kkk           ¦ jjj           ¦               ¦               ¦
+-------------------------------------------------------------------------------------------------------------------------

I want to merge multiple rows from above table belonging to same employee into one -

+-------------------------------------------------------------------------------------------------------------
¦ EMP_ID     ¦ ATTR1_OLD_VAL ¦ ATTR1_NEW_VAL ¦ ATTR2_OLD_VAL ¦ ATTR2_NEW_VAL ¦ ATTR3_OLD_VAL ¦ ATTR3_NEW_VAL ¦
¦------------+---------------+---------------+---------------+---------------+---------------+---------------¦
¦       E001 ¦ pqr           ¦ abc           ¦ xxx           ¦ yyy           ¦ zzz           ¦ aaa           ¦
¦       E002 ¦ aaa           ¦ ccc           ¦ kkk           ¦ jjj           ¦ fff           ¦ ppp           ¦
+-------------------------------------------------------------------------------------------------------------

I came to know about MERGE statement but not sure if it will work. I am new to oracle pl/sql.

CREATE TABLE tmp 
  ( 
     row_id NUMBER, 
     id     NUMBER, 
     t1     VARCHAR2(5), 
     t2     VARCHAR2(5), 
     t3     VARCHAR2(5) 
  ); 

INSERT INTO tmp 
VALUES      (1, 
             1, 
             'a', 
             NULL, 
             'a'); 

INSERT INTO tmp 
VALUES      (2, 
             1, 
             NULL, 
             'b', 
             'b'); 

INSERT INTO tmp 
VALUES      (3, 
             1, 
             'c', 
             NULL, 
             NULL); 

INSERT INTO tmp 
VALUES      (1, 
             2, 
             'a', 
             'a', 
             NULL); 

INSERT INTO tmp 
VALUES      (2, 
             2, 
             NULL, 
             'b', 
             NULL); 

So, we should get: 1,C,B,B and 2,A,B,NULL:

select id_merged, T1,T2,T3 from 
( SELECT id id_merged,
 first_value(T1 IGNORE nulls) over (partition BY id ORDER BY row_id DESC) T1,
 first_value(T2 IGNORE nulls) over (partition BY id ORDER BY row_id DESC) T2,
 first_value(T3 IGNORE nulls) over (partition BY id ORDER BY row_id DESC) T3,
 rank () over (partition by id order by row_id) rn
FROM tmp)
where rn=1 ORDER BY id_merged;

You may use a group by emp_id and choose a value for attributes using keep dense_rank :

select 
  emp_id,
  max(ATTR1_OLD_VAL) keep (dense_rank first order by decode(ATTR1_OLD_VAL,null,1,0), stage_id desc) as ATTR1_OLD_VAL
from STAGE_TABLE
group by emp_id;

order by decode(ATTR1_OLD_VAL,null,1,0) put null values to the end. From those with non-null values choose the latest with stage_id desc .

I've put a single attribute you should put the others.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM