I need a query that returns all the rows from colA paired with colB but to treat the same values in the opposite direction as duplicates and to be removed.
The best
My SQL has the functions least()
and greatest()
. A query that returns the unique pairs:
select least(colA, colB), greatest(cola, colB)
from t
group by least(colA, colB), greatest(cola, colB)
However, this could rearrange the values of non-duplicated rows. For instance, if a row were (z, a), the result here would be (a, z).
To fix this, we need to find the right values. The idea is to count the number of times that each version of the pair appears. If it appears twice, then which is chosen seems to be arbitrary. If once, then we need to get the original row out.
Here is a version that does this:
select (case when cnt = 1 then colA else l end) as ColA,
(case when cnt = 1 then colB else g end) as ColB
from (select least(colA, colB) as l, greatest(cola, colB) as g,
count(distinct colA) as cnt, min(colA) as colA, min(colB) as colB
from t
group by least(colA, colB), greatest(cola, colB)
) t
What is this doing? The original query finds the unique pairs. In the subquery, it counts the number of times that each version of the pair appears in the data and it includes colA
and colB
as columns.
The outer query then chooses what to show for each identified pair. If the count is 1 -- only one version of the pair -- then min(colA)
is ColA, and min(colB)
is colB. So, use those. Otherwise, it arbitrarily chooses the pair where ColA < ColB.