简体   繁体   中英

Oracle SQL compare records within a table

I have a table like below:

S.No | Item_ID | Item_Revision | Code |
-----+---------+---------------+-------
1.   | item1   | 0             | xyz  |
2.   | item2   | 0             | xyz  |
3.   | item3   | 0             | xyz  |
4.   | item1   | 1             |      |
5.   | item2   | 1             | abc  |
6.   | item3   | 1             | xyz  |

I need to compare the records in the table to find the differences in code in different revisions of the items.

I want the result set as below:

 | Item_ID | Code_Revision_0 | Code_Revision_1 |
 | item1   | xyz             |                 |
 | item2   | xyz             | abc             |

I am not able to formulate an oracle query for this purpose.

Thanks in advance!

You can use a self join to do this.

select t1.item_id, t1.code code_rev_0, t2.code code_rev_1
from tablename t1
join tablename t2 on t1.item_id=t2.item_id 
and t1.item_revision = 0 and t2.item_revision = 1
where nvl(t1.code,'a') <> nvl(t2.code,'a')

One basic idea is to use join :

select t0.item_id, t0.code as code_0, t1.code as code_1
from t t0 join
     t t1
     on t0.item_id = t1.item_id and
        t0.item_revision = 0 and
        t1.item_revision = 1
where t0.code <> t1.code;

However, if the code value is NULL (or an empty string), you need to be more careful:

where t0.code <> t1.code or (t0.code is null and t1.code is not null) or
      (t0.code is not null and t1.code is null) 

Here is a solution that uses the PIVOT operator instead of a self-join. If I am reading the execution plans correctly, this is slightly more efficient (cost of 13 vs. 17 for the join solution) for the input data you provided. You may want to test the two solutions on your actual data to see which works better.

with
     input_data ( item_id, item_revision, code ) as (
       select 'item1', 0, 'xyz' from dual union all
       select 'item2', 0, 'xyz' from dual union all
       select 'item3', 0, 'xyz' from dual union all
       select 'item1', 1, ''    from dual union all
       select 'item2', 1, 'abc' from dual union all
       select 'item3', 1, 'xyz' from dual
     )
select *
from input_data
pivot (max(code) for item_revision in (0 as code_revision_0, 1 as code_revision_1))
where code_revision_0              != code_revision_1 
   or code_revision_0 is     null and code_revision_1 is not null
   or code_revision_0 is not null and code_revision_1 is     null
;

OUTPUT :

ITEM_ CODE_REVISION_0  CODE_REVISION_1
----- ---------------- ----------------
item1 xyz
item2 xyz              abc

2 rows selected.

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