update your_table
set status='Matched'
where id in(
with IDS(id1,id2,grp,num,rnum) as(
select a.id,b.id,
rank() over(order by a.tdate,a.price,a.product,a.quantity),
case when a.id=lag(a.id) over(partition by a.tdate,a.price,a.product,a.quantity order by a.id)
then 0
else dense_rank() over(partition by a.tdate,a.price,a.product,a.quantity order by a.id) end,
row_number() over(partition by a.tdate,a.price,a.product,a.quantity order by a.id)
from your_table a, your_table b
where a.tdate=b.tdate and a.price=b.price and a.product=b.product
and a.quantity=b.quantity
and a.buysell='Sell' and b.buysell='Buy' and a.description!=b.description
),
Q(id1,id2,grp,num,used) as(
select id1,id2,grp,num,','||id2||','
from IDS where rnum=1
union all
select I.id1,R.column_value,Q.grp,Q.num+1,Q.used||R.column_value||','
from Q, IDS I,
table(cast(multiset(
select min(id2) id from IDS N
where N.id1=I.id1
and Q.used not like '%,'||N.id2||',%'
) as sys.ODCINumberList)) R
where I.grp=Q.grp and I.num=Q.num+1
)
select decode(X,1,id1,id2)
from Q,
(select 1 X from DUAL union all select 2 from DUAL)
where id2 is not null
)