Reputation: 1689
Somehow MS Access doesn't seem to have access to the keyword INTERSECT, which I need right now in order to fix some data errors in my database.
I had a look on older questions and found some answers that tried to solve this problem by using a select distinct [...] inner join [...] construction.
However, this doesn't seem to help me, as the syntax doesn't apply to the table I need to intersect.
Here's a short explanation on what I want to achieve with the INTERSECT:
My table looks like this (simplified):
A | B
hello | world
world | hello
Now these datasets are redundant, but unfortunately can't be caught by a constraint, as they are not exactly the same, but mirrored. That's why they got inserted in the first place...
I think normally I would be able to select all the affected data sets by using a
SELECT A,B FROM tbl
INTERSECT
SELECT B,A from tbl
After having selected them I could just delete them and would be rid of that problem... Does anyone have an idea on how to implement this using MS Access?
Upvotes: 1
Views: 13243
Reputation: 123654
For test data in a table named [MirrorTest]
pk A B
-- ----- -----
1 foo bar
2 hello world
3 hello there
4 world hello
5 bar baz
6 bar foo
the query
SELECT pk, A, B
FROM MirrorTest
WHERE A<=B
UNION ALL
SELECT pk, B, A
FROM MirrorTest
WHERE A>B
will return all of the rows such that A<=B, i.e.,
pk A B
-- ----- -----
2 hello world
3 hello there
5 bar baz
6 bar foo
1 bar foo
4 hello world
Wrap that in an aggregation query to find the candidates for deletion, defined as the larger [pk] value where there are duplicates
SELECT Max(pk) AS pkToDelete
FROM
(
SELECT pk, A, B
FROM MirrorTest
WHERE A<=B
UNION ALL
SELECT pk, B, A
FROM MirrorTest
WHERE A>B
) AS u
GROUP BY A, B
HAVING COUNT(*) > 1
returns
pkToDelete
----------
6
4
so you could just use that in the WHERE clause of a DELETE query
DELETE FROM MirrorTest
WHERE pk IN
(
SELECT Max(pk) AS pkToDelete
FROM
(
SELECT pk, A, B
FROM MirrorTest
WHERE A<=B
UNION ALL
SELECT pk, B, A
FROM MirrorTest
WHERE A>B
) AS u
GROUP BY A, B
HAVING COUNT(*) > 1
)
Upvotes: 4