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
If you prefer a "clean" SQL solution (without least()
or greatest()
) this also does your job:
select colA, colB from your_table
where colA > colB
or (colB, colA) not in (select colA, colB from your_table)
SQL fiddle
Try this:
select t3.colA,t3.colB
from table_name t3
where (t3.colA,t3.colB)
not in
(select greatest(t1.colA, t1.colB), least(t1.cola, t1.colB)
from table_name t1 , table_name t2
where t1.colB=t2.colA and t1.colA=t2.colB
group by greatest(t1.colA,t1.colB), least(t1.cola, t1.colB))
SQL FIDDLE
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.