Reputation: 928
I have a table that contains an even number of rows. The rows form pairs with the same information but the content of the first two columns swapped. Here is an example with three columns:
1 2 3
=======
A B W
B A W
C D X
D C X
E F Y
H G Z
F E Y
G H Z
My actual table has many more columns, but the content is always the same within a pair.
I'm looking for an SQL-Statement that gets rid of one row of each pair. The result should look like this:
1 2 3
=======
A B W
C D X
E F Y
G H Z
My table is generated by a script (which I can't change), so I assume my input is correct (every row has a partner, rows >=3 are the same for each pair). A statement that could check these preconditions would be extra cool.
Upvotes: 2
Views: 103
Reputation: 6073
For Me the below code is working
DECLARE @TEST TABLE
(A CHAR(1),B CHAR(1),C CHAR(1))
INSERT INTO @TEST VALUES
('A','B','W'),
('B','A','W'),
('C','D','X'),
('D','C','X'),
('E','F','Y'),
('H','G','Z'),
('F','E','Y'),
('G','H','Z')
SELECT MIN(A) [1],
MAX(A) [2],
C [3]
FROM @TEST
GROUP BY C
Result:
Upvotes: 1
Reputation: 32392
If every row has a counterpart where c1 and c2 are swapped then just select rows where c1 and c2 are in a certain order (i.e. c1 < c2).
The EXISTS
part makes sure that only rows that have a counterpart are shown. If you want to show all unique rows regardless of whether or not they have a counterpart, then change the last condition from AND EXISTS
to OR NOT EXISTS
.
SELECT * FROM myTable t1
WHERE c1 < c2
AND EXISTS (
SELECT * FROM myTable t2
WHERE t2.c1 = t1.c2
AND t2.c2 = t1.c1
AND t2.c3 = t1.c3
) ORDER BY c1
Upvotes: 1
Reputation:
You didn't state your DBMS so this is ANSI SQL:
select least(c1,c2),
greatest(c1,c2),
min(c3) -- choose min or max to your liking
from the_table
group by least(c1,c2), greatest(c1,c2)
Upvotes: 1
Reputation: 9904
Something similar would help using ROWNUM and CTE
with test_Data as
(
SELECT COL1, COL2, COL3, ROWNUM ROWCOUNT FROM
(
SELECT 'A' COL1, 'B' COL2, 'W' COL3 FROM DUAL UNION
SELECT 'B' COL1, 'A' COL2, 'W' COL3 FROM DUAL UNION
SELECT 'C' COL1, 'D' COL2, 'X' COL3 FROM DUAL UNION
SELECT 'D' COL1, 'C' COL2, 'X' COL3 FROM DUAL
) ORDER BY COL3, COL1
)
SELECT TAB1.COL1, TAB1.COL2, TAB1.COL3 FROM TEST_DATA TAB1, TEST_DATA TAB2
WHERE
TAB1.COL1 = TAB2.COL2
AND TAB1.COL2 = TAB2.COL1
AND TAB1.COL3 = TAB2.COL3
AND TAB1.ROWCOUNT = TAB2.ROWCOUNT+1;
Your query without testdata would be,
with CTE as
(SELECT COL1, COL2, COL3, ROWNUM ROWCOUNT FROM MY_TABLE ORDER BY COL3,COL1)
SELECT TAB1.COL1, TAB1.COL2, TAB1.COL3 FROM CTE TAB1, CTE TAB2
WHERE
TAB1.COL1 = TAB2.COL2
AND TAB1.COL2 = TAB2.COL1
AND TAB1.COL3 = TAB2.COL3
AND TAB1.ROWCOUNT = TAB2.ROWCOUNT+1;
Upvotes: 1