Reputation: 476
i have two tables in oracle --> master_file
and payment
tables.
master_file table:
id (primary key), nama, status
41121, john, PL
41122, ryan, UP
41121, john, UP
there are duplicate data in columns id ( id 41121 ) . I do not know where the mistake , so the id column can store duplicate data .
payment table:
id, idr
41121, 1000
41122, 500
my query :
select a.id,a.nama,a.status,b.idr from master_file a, payment b
where a.id=b.id(+)
result
id, nama, status, idr
41121, john, PL, 1000
41122, ryan, UP, 500
41121, john, UP, 1000
i want result
id, nama, status, idr
41121, john, PL, 1000
41122, ryan, UP, 500
i know, i cannot use distinct to remove row : 41121, john, UP, 1000.
give me solution, please. thanks before. :)
Upvotes: 0
Views: 69
Reputation: 191435
Your master table cannot have a primary key on ID as it has duplicate values; perhaps it has a foreign key or a composite primary key, say on ID and status.
Assuming your data and data model are correct and you don't want to modify it, you need to establish the precedence of the possible status values. From your question it seems PL takes precedence over UP, but there may be other possible values, and you may have more than two rows for a given ID. Once you know the precedence you can use that in a case statement to create a numeric equivalent and use that to rack the 'duplicate' rows:
select a.id, a.nama, a.status, b.idr,
dense_rank() over (partition by a.id order by
case a.status when 'UP' then 1 when 'PL' then 2 else 0 end desc) as rnk
from master_file a
left join payment b on b.id = a.id
order by a.id;
ID NAMA STATUS IDR RNK
---------- ---------- ------ ---------- ----------
41121 john PL 1000 1
41121 john UP 1000 2
41122 ryan UP 500 1
You can then use that as an inline view and filter out all but the highest-precedence rows:
select id, nama, status, idr
from (
select a.id, a.nama, a.status, b.idr,
dense_rank() over (partition by a.id order by
case a.status when 'UP' then 1 when 'PL' then 2 else 0 end desc) as rnk
from master_file a
left join payment b on b.id = a.id
)
where rnk = 1
order by id;
ID NAMA STATUS IDR
---------- ---------- ------ ----------
41121 john PL 1000
41122 ryan UP 500
It's also possible to use an inline view that filter the master_file
before joining, but that's largely a matter of preference.
If the possible status values are in another reference table, and their precedence is established in that table, then you could join to that instead of doing it manually through case
.
Upvotes: 1
Reputation: 4867
You want to remove the row with 'UP' in it?
In that case you need to include it as another item in your WHERE
clause:
... where a.id=b.id(+) and status = 'UP'
Upvotes: 0