Nevin Thomas
Nevin Thomas

Reputation: 826

How to remove duplicate rows from a join query in oracle?

I have two tables bc_transactions & bc_messages. I used the below query to join these two tables

SELECT distinct(bt.USER_TRANS_ID),bm.TS,bm.STATUS
FROM bc_transactions bt
inner JOIN bc_messages bm
ON bt.USER_TRANS_ID=bm.USER_MESSAGE_ID
where bt.protocol_name  = 'Gateway'
and bt.STATUS=bm.STATUS
AND bt.startdate >=TRUNC(SYSDATE-2)
AND bt.startdate <=TRUNC(SYSDATE-1)
AND bt.STATUS like 'ERROR TRANSPORT'
AND bt.HOSTNAME='HEB'
order by bt.USER_TRANS_ID ASC;

the bc_messages table has multiple rows with status as ERROR TRANSPORT which have the same USER_MESSAGE_ID at different timestamp(bm.TS). I am trying to get only the latest row.

|USER_TRANS_ID |            TS        |   STATUS            |
-------------------------------------------------------------
| ID1          | 10-03-2020  15:01:23 |   ERROR TRANSPORT   |
| ID1          | 10-03-2020  15:15:23 |   ERROR TRANSPORT   |
| ID1          | 10-03-2020  15:30:23 |   ERROR TRANSPORT   |
| ID1          | 10-03-2020  15:35:23 |   ERROR TRANSPORT   |
| ID2          | 10-03-2020  16:10:23 |   ERROR TRANSPORT   |
| ID2          | 10-03-2020  16:11:23 |   ERROR TRANSPORT   |

Upvotes: -1

Views: 177

Answers (3)

Popeye
Popeye

Reputation: 35930

You can use the ROW_NUMBER analytical function as follows:

SELECT USER_TRANS_ID, TS, STATUS FROM 
(SELECT bt.USER_TRANS_ID,bm.TS,bm.STATUS, 
ROW_NUMBER() OVER (PARTITION BY bt.USER_TRANS_ID , bm.STATUS 
                   ORDER BY bm.TS DESC NULLS LAST) AS RN -- added this
FROM bc_transactions bt
inner JOIN bc_messages bm
ON bt.USER_TRANS_ID=bm.USER_MESSAGE_ID
where bt.protocol_name  = 'Gateway'
and bt.STATUS=bm.STATUS
AND bt.startdate >=TRUNC(SYSDATE-2)
AND bt.startdate <=TRUNC(SYSDATE-1)
AND bt.STATUS like 'ERROR TRANSPORT'
AND bt.HOSTNAME='HEB')
WHERE RN = 1 -- added this
order by bt.USER_TRANS_ID ASC;

Upvotes: 1

subin ashok
subin ashok

Reputation: 1

take max of timestamp using group by

select
     bt.USER_TRANS_ID,max(bm.TS),bm.STATUS
 FROM
     bc_transactions bt
     inner JOIN bc_messages bm ON bt.USER_TRANS_ID=bm.USER_MESSAGE_ID
 where
     bt.protocol_name  = 'Gateway'
     and bt.STATUS=bm.STATUS<br>
     AND bt.startdate >=TRUNC(SYSDATE-2)
     AND bt.startdate <=TRUNC(SYSDATE-1)
     AND bt.STATUS like 'ERROR TRANSPORT' // its better to keep status without space
     AND bt.HOSTNAME='HEB'
 group by
     bt.USER_TRANS_ID,bm.STATUS
 order by bt.USER_TRANS_ID ASC;

Upvotes: 0

Yogesh Sharma
Yogesh Sharma

Reputation: 50173

You can use row_number() :

select t.*
from (select bt.USER_TRANS_ID, bm.TS,bm.STATUS,
             row_number() over (partition by bt.USER_TRANS_ID order by bm.TS desc) as seq
      from bc_transactions bt inner join
            bc_messages bm
            on bt.USER_TRANS_ID = bm.USER_MESSAGE_ID
       where bt.protocol_name  = 'Gateway' and 
             bt.STATUS=bm.STATUS and 
             bt.startdate >= TRUNC(SYSDATE-2) and 
             bt.startdate <= TRUNC(SYSDATE-1) and 
             bt.STATUS like 'ERROR TRANSPORT' and 
             bt.HOSTNAME = 'HEB'
     ) t
where seq = 1;

Upvotes: 1

Related Questions