Assuming both tables have the same row type: all the same column names and types (at least compatible), you can work with row types to simplify:
SELECT (t).*
FROM (SELECT t, count(*) AS ct1 FROM table_1 t GROUP BY 1) t1
JOIN (SELECT t, count(*) AS ct2 FROM table_2 t GROUP BY 1) t2 USING (t)
WHERE t1.ct1 > 1
OR t2.ct2 > 1;
- Group duplicates and remember the count in each table.
- Join the two tables, which removes all rows without match in the other table.
- Filter rows where at least one side has more than one copy.
- In the outer
SELECT
decompose the row type to get columns as usual.
I don't return row counts. If you need those, add ct1
and ct2
in the outer SELECT
.
This requires every column type to support the equality operator =
.
A prominent example that does not is json
. (But jsonb
does.) See:
If you have such columns, cast to text
to work around it. Or you can work with hash values - which also helps performance for very wide rows and/or many duplicates. Related: