Home > database >  Exclude rows having similar columns with another row(s)
Exclude rows having similar columns with another row(s)

Time:12-31

Let's suggest I have the following table of rates:

  ID   |   baseAsset  |    quoteAsset  
------- -------------- -----------------
   1   |     BTC      |      USDT         
   2   |     USDT     |      BTC         
   3   |     LUNA     |      ETH          
   4   |     ETH      |      LUNA         
   5   |     USD      |      BTC          

The problem is that I have no idea how to get rates and exclude those rates that have reverse pair. E.g. for my case I want to get something like this:

  ID   |   baseAsset  |    quoteAsset  
------- -------------- -----------------
   1   |     BTC      |      USDT        
   3   |     LUNA     |      ETH          
   5   |     USD      |      BTC          

Now there is only BTC/USDT (without USDT/BTC). So, the query should take only first pair (no matter BTC/USDT, or LUNA/ETH, or another one) and find reverse pair to exclude. If there should be additional column (like createdAt or updatedAt) — correct me and let me know if my question still is not clear, please.

P.S. Answers with pure SQL lang are accepted also.

CodePudding user response:

In SQL you'd use LEAST and GREATEST for this, provided your DBMS supports these functions:

select
  min(id),
  least(baseAsset, quoteAsset) as asset1,
  greatest(baseAsset, quoteAsset) as asset2,
from mytable
group by least(baseAsset, quoteAsset), greatest(baseAsset, quoteAsset)
order by min(id);

In standard SQL you can replace above LEAST by

CASE WHEN baseAsset < quoteAsset THEN baseAsset ELSE quoteAsset END

and above GREATEST by

CASE WHEN baseAsset > quoteAsset THEN baseAsset ELSE quoteAsset END

Another simple approach is to use NOT EXISTS:

select *
from mytable
where not exists
(
  select null
  from mytable reverse
  where reverse.baseAsset = mytable.quoteAsset
  and reverse.quoteAsset = mytable.baseAsset
  and reverse.id < mytable.id
);
  • Related