Une option consiste à utiliser une FULL OUTER JOIN entre les deux tables sous la forme suivante:
SELECT count (1)
FROM table_a a
FULL OUTER JOIN table_b b
USING (<list of columns to compare>)
WHERE a.id IS NULL
OR b.id IS NULL ;
Par exemple:
CREATE TABLE a (id int, val text);
INSERT INTO a VALUES (1, 'foo'), (2, 'bar');
CREATE TABLE b (id int, val text);
INSERT INTO b VALUES (1, 'foo'), (3, 'bar');
SELECT count (1)
FROM a
FULL OUTER JOIN b
USING (id, val)
WHERE a.id IS NULL
OR b.id IS NULL ;
Renvoie un nombre de 2, alors que:
CREATE TABLE a (id int, val text);
INSERT INTO a VALUES (1, 'foo'), (2, 'bar');
CREATE TABLE b (id int, val text);
INSERT INTO b VALUES (1, 'foo'), (2, 'bar');
SELECT count (1)
FROM a
FULL OUTER JOIN b
USING (id, val)
WHERE a.id IS NULL
OR b.id IS NULL ;
renvoie le nombre espéré de 0.
Ce que j'aime dans cette méthode, c'est qu'elle n'a besoin de lire chaque table qu'une seule fois que de lire chaque table deux fois lorsque vous utilisez EXISTS. De plus, cela devrait fonctionner pour toute base de données qui prend en charge les jointures externes complètes (pas seulement Postgresql).
Je décourage généralement l'utilisation de la clause USING, mais voici une situation où je pense que c'est la meilleure approche.
Addendum 2019-05-03:
S'il y a un problème avec des données nulles possibles (c'est-à-dire que la colonne id n'est pas nullable mais que la valeur l'est), vous pouvez essayer ce qui suit:
SELECT count (1)
FROM a
FULL OUTER JOIN b
ON ( a.id = b.id
AND a.val IS NOT DISTINCT FROM b.val )
WHERE a.id IS NULL
OR b.id IS NULL ;
EXCEPT
, vérifiez cette question: Un moyen efficace de comparer deux grands ensembles de données dans SQL