Skip to content Skip to sidebar Skip to footer

Compare Rows In Oracle Table And Update Matching Ones

I have a table such as the following: **ID tDate Product Price Quantity BuySell Status** 1 10-May-17 pppp $12 20 Buy

Solution 1:

Untested but something like this using only SQL:

MERGE INTO your_table dst
USING (
  SELECT ROW_NUMBER() OVER (
             PARTITION BY tDate, Product, Price, Quantity, BuySell
             ORDER BY ID
           ) AS idx,
         COUNT( CASE BuySell WHEN 'Buy' THEN 1 END ) OVER (
             PARTITION BY tDate, Product, Price, Quantity
           ) AS num_buy,
         COUNT( CASE BuySell WHEN 'Sell' THEN 1 END ) OVER (
             PARTITION BY tDate, Product, Price, Quantity
           ) AS num_sell
  FROM   your_table
) src
ON ( src.ROWID = dst.ROWID AND src.idx <= LEAST( src.num_buy, src.num_sell ) )
WHEN MATCHED THEN
  UPDATE SET Status = 'Matched';

Solution 2:

You can get the number of buy-sell pairs per tdate and update such rows.

MERGE INTO tablename dst
USING (select t.*,count(*) over(partition by tDate,Product,Price,Quantity,rn) as cnt 
       from (select t.*,row_number() over(partition by tDate,Product,Price,Quantity,buysell order by id) as rn
             from tablename t) t
       ) src
ON (src.id = dst.id AND src.cnt=2)
WHEN MATCHED THEN
UPDATE SET Status = 'Matched';

Run this query to see how row numbers are assigned to buy-sell.

select t.*,count(*) over(partition by tDate,Product,Price,Quantity,rn) as cnt 
from (select t.*,row_number() over(partition by tDate,Product,Price,Quantity,buysell order by id) as rn
      from tablename t) t

Solution 3:

here's another perspective to add to the others. This addresses only the matching portion and not the update or merge part. I had a similar problem recently where I needed to find records that matched on transaction date and location, but came from two different sources. In this case the records have to already be sorted so that the like records will be together. The inner query compares the record to the one before and the one after and grabs it if they match. Then the outer query determines if they meet the 'difference' criteria. Hope this helps.

select sbs.trnsid, sbs.amount, sbs.transaction_date, sbs.posted_date, sbs.srcid, 
        sbs.credited_flag, sbs.accid, sbs.compid, sbs.badgeid, sbs.locid, sbs.date_credited, 
        sbs.searchable, sbs.priortime, sbs.nexttime, sbs.priorsource, sbs.nextsource 
    from 
    (select trnsid, amount, transaction_date, posted_date, srcid, credited_flag,
      accid, compid, badgeid, locid, date_credited, transaction_date||locid as searchable,
      lag(transaction_date||locid, 1) over (order by accid) as priortime,
      lead(transaction_date||locid, 1) over (order by accid) as nexttime, 
    lag(srcid, 1) over (order by accid) as priorsource, 
    lead(srcid, 1) over (order by accid) as nextsource
    from transactions_table
    where accid = v_acct
      and transaction_date >= to_date('10/01/2016 00:00:00', 'mm/dd/yyyy hh24:mi:ss') 
      and transaction_date <= to_date('04/23/2017 23:59:59', 'mm/dd/yyyy hh24:mi:ss')
      and srcid in ('B', 'S') order by accid, transaction_date, locid) sbs
    where (sbs.searchable = sbs.nexttime and sbs.srcid = 'S' and sbs.nextsource = 'B')
   or (sbs.searchable = sbs.priortime and sbs.srcid = 'B' and sbs.priorsource = 'S');

Solution 4:

merge into mytable t3
using (select t1.*, count(*) over (partition by tdate,product,price,quantity,field) as field2 from
(
select mytable.*, row_number() over (partition by mytable.tdate,mytable.product,mytable.price,mytable.quantity,mytable.buysell 
order by id) field from 
mytable) t1)  t2
on (t2.id=t3.id and t2.field2='2')
when matched then 
update set status='Matched';

Post a Comment for "Compare Rows In Oracle Table And Update Matching Ones"