Reputation: 315
I have a table that has two columns in it:
primId column1 column2
1 98 62
2 62 98
3 3 105
4 105 3
5 11 4
I need to get second row, fourth row, fifth row. if 98,62 has appeared once then 62,98 cannot appear (if possible I need latest value). I have taken help from this link Removing Mirrored Pairs from SQL Join, but got no luck. These values are not related to each other in greater or lesser. Please let me know how I can get this result. Is this possible with Sql query. Thanks
Upvotes: 1
Views: 1682
Reputation: 5926
You can do it this way:
select t1.*
from yourTable t1
left join
yourTable t2
on t1.column1 = t2.column2 and
t1.column2 = t2.column1
where t2.column1 is null or
t1.column1 > t1.column2
The mirrored rows will be joined, and you will only take them once due to the second where
condition, and the rows that are not mirrored will not be joined, so you'll get them with the first where
condition.
Edit
To have the last couple returned, you can use this approach instead
select t1.*
from yourTable t1
join (
select max(primId) as primId,
case when column1 > column2 then column2 else column1 end c1,
case when column1 < column2 then column2 else column1 end c2
from yourTable
group by case when column1 > column2 then column2 else column1 end,
case when column1 < column2 then column2 else column1 end
) t2
on t1.primId = t2.primId
The inner query will return the highest primId
for each couple, regardless of the order. Joining it with the source table, you use it as a filter.
You can see it working here
Upvotes: 3
Reputation: 1271231
If you want to ensure that you keep the original pairs (so 4,1 would not be allowed as output), then the following should be very efficient:
select t.*
from t
where t.column1 <= t.column2
union all
select t.*
from t
where t.column1 > t.column2 and
not exists (select 1 from t t2 where t2.column1 = t.column2 and t2.column2 = t.column1);
For optimal performance, you want an index on t(column1, column2)
.
Upvotes: 0
Reputation: 49270
When it doesn't matter if the row in the result-set of the query exists in the table, you can use least
and greatest
so that one row per pair is retrieved.
select distinct least(column1,column2) as col1, greatest(column1,column2) as col2
from tablename
If the row retrieved has to be present in the table, use the previous query and join it to the existing table.
select t.column1,t.column2
from tablename t
left join (select least(column1,column2) as col1, greatest(column1,column2) as col2
from tablename
group by least(column1,column2), greatest(column1,column2)
having count(*)>1
) x on x.col1=t.column1 and x.col2=t.column2
where x.col1 is null and x.col2 is null
Upvotes: 0
Reputation: 72235
You can use the following query:
SELECT DISTINCT LEAST(column1, column2) AS column1,
GREATEST(column1, column2) AS column2
FROM mytable
Note: The above query works provided the field order is irrelevant to you. Otherwise you have to use a JOIN
like @Stefano proposes.
Upvotes: 0