Trouver les lignes d'une table absentes d'une autre

La norme SQL évolue : tirez le meilleur d'un SGBD qui la respecte en écrivant du SQL moderne avec en complément PL/pgSQL, php, java etc.
Répondre
Phil
Administrateur du site
Messages : 244
Enregistré le : mar. 1 sept. 2015 00:38
Localisation : France
Contact :

Trouver les lignes d'une table absentes d'une autre

Message par Phil » lun. 2 sept. 2019 16:21

Merci à Lionel pour sa question :

"Je cherche à contrôler les données d'un applicatif dont les données sont dans Oracle et PostgreSQL. Il faut que je trouve les données d'une table absentes d'une autre. L'exemple est simplifié par rapport au vrai cas mais j'utilise cette syntaxe :

Code : Tout sélectionner

select 
c1,
c2
from t1 ok
where not exists
(select 1
from t2 ano
where ok.c1 = ano.c1 
and ok.c2 = ano.c2
);
Ce n'est pas bon : j'obtiens toutes les lignes de la table ok alors qu'il y a beaucoup de lignes qui devraient être dans la table ano. Que faut -il changer ?"

Réponse :

Il y a probablement des valeurs nulles dans certaines colonnes. NULL=NULL ne donne pas vrai. Il faudrait utiliser "IS NOT DISTINCT FROM" au lieu de "=" pour garder cette syntaxe.
Exemple :

Code : Tout sélectionner

select version();
                                                    version
----------------------------------------------------------------------------------------------------------------
 PostgreSQL 11.5 (Debian 11.5-1+deb10u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit


create table t1 (c1 int, c2 text);

create table t2 (c1 int, c2 text);

insert into t1(c1) values(1);
insert into t1(c1) values(2);
insert into t1(c1) values(3);

insert into t2(c1) values(1);
insert into t2(c1) values(2);

select 
c1,
c2
from t1 ok
where not exists
(select 1
from t2 ano
where ok.c1 = ano.c1 
and ok.c2 = ano.c2
);

 c1 | c2
----+----
  1 |
  2 |
  3 |
(3 lignes)

select 
c1,
c2
from t1 ok
where not exists
(select 1
from t2 ano
where ok.c1 is not distinct from ano.c1 
and ok.c2 is not distinct from ano.c2
);

 c1 | c2
----+----
  3 |
(1 ligne)
Même dans sa version 19c, Oracle ne comprend pas la syntaxe SQL:2003 "IS NOT DISTINCT FROM".
Il est de toute façon sans doute plus évident de travailler avec un opérateur ensembliste.
EXCEPT avec PostgreSQL :

Code : Tout sélectionner

select 
c1,
c2
from t1 ok
except 
select 
c1,
c2
from t2 ano;

 c1 | c2
----+----
  3 |
(1 ligne)
MINUS avec Oracle :

Code : Tout sélectionner

Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

select 
c1,
c2
from t1 ok
minus
select 
c1,
c2
from t2 ano;

        C1         C2
---------- ----------
         3
Cdlt. Phil - pgphil.ovh

Répondre