如何从oracle中的连接查询中删除重复行?
How to remove duplicate rows from a join query in oracle?
我有两个 tables bc_transactions & bc_messages。我使用下面的查询来加入这两个 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;
bc_messages table 有多个状态为 ERROR TRANSPORT 的行,它们在不同的时间戳 (bm.TS) 具有相同的 USER_MESSAGE_ID。我试图只获取最新的行。
|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 |
您可以使用 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;
您可以使用ROW_NUMBER
分析函数如下:
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;
干杯!!
使用 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;
我有两个 tables bc_transactions & bc_messages。我使用下面的查询来加入这两个 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;
bc_messages table 有多个状态为 ERROR TRANSPORT 的行,它们在不同的时间戳 (bm.TS) 具有相同的 USER_MESSAGE_ID。我试图只获取最新的行。
|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 |
您可以使用 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;
您可以使用ROW_NUMBER
分析函数如下:
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;
干杯!!
使用 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;