Overblog
Suivre ce blog
Editer l'article Administration Créer mon blog
18 juillet 2013 4 18 /07 /juillet /2013 10:58

Un des grands problèmes dans ma vie, c'est ma passion pour le NATURAL FULL OUTER JOIN. Parce qu'il y a plein de mots, c'est full, le côté naturel, les joints et tout ça.


Et cette lubie m'a encore piégée hier lorsque je faisais une simple comparaison de données avant / après traitement.


Allez, démonstration par étape : 


1) Deux tables correspondant aux données avant / après


SQL>CREATE TABLE tab_avant AS

  2  SELECT level l

  3  FROM dual

  4  CONNECT BY level <= 5;


Table created.


Elapsed: 00:00:00.09

SQL>CREATE TABLE tab_apres AS

  2  SELECT level + 2 l

  3  FROM dual

  4  CONNECT BY level <= 5;


Table created.


Elapsed: 00:00:00.03


2) Pour comparer, minus ou natural machin : 


La version minus me barbe un peu, parce qu'il faut écrire A - B et B - A : 


SQL>SELECT '+ap', a.*

  2  FROM tab_apres a

  3  MINUS

  4  SELECT '+ap', b.*

  5  FROM tab_avant b

  6  UNION ALL

  7  SELECT '+av', c.*

  8  FROM tab_avant c

  9  MINUS

 10  SELECT '+av', d.*

 11  FROM tab_apres d;


'+A          L

--- ----------

+ap          6

+ap          7

+av          1

+av          2


En revanche, la version natural full outer join me semble beaucoup plus drôle :


SQL>SELECT case when b.rowid is null then '+av' when a.rowid is null then '+ap' end, l

  2  FROM tab_avant a

  3    NATURAL FULL OUTER JOIN tab_apres b

  4  WHERE a.rowid is null OR b.rowid is null;


CAS          L

--- ----------

+av          1

+av          2

+ap          6

+ap          7


Elapsed: 00:00:00.03


"Natural" pour dire qu'on match sur toutes les colonnes de même nom (à n'utiliser que pour rigoler sous peine de se faire virer), outer join parce qu'on prend aussi ce qui ne matche pas, et full parce que c'est outer des deux côtés.


3) Une défaite supplémentaire


Seulement voilà, il y a des choses qui ne sont pas comparables... ajoutons une colonne vide dans chaque table : 


SQL>ALTER TABLE tab_avant ADD c number;


Table altered.


Elapsed: 00:00:00.06

SQL>ALTER TABLE tab_apres ADD c number;


Table altered.


Elapsed: 00:00:00.03


... et relançons la comparaison :


SQL>SELECT case when b.rowid is null then '+av' when a.rowid is null then '+ap' end, l, c

  2  FROM tab_avant a

  3    NATURAL FULL OUTER JOIN tab_apres b

  4  WHERE a.rowid is null OR b.rowid is null;


CAS          L          C

--- ---------- ----------

+av          1

+av          4

+av          3

+av          2

+av          5

+ap          6

+ap          7

+ap          5

+ap          4

+ap          3


10 rows selected.


Patatra, ça devient n'importe quoi. Le "natural" ne doit pas faire oublier qu'on teste "colonne a" = "colonne b" dans la jointure.

Et la comparaison NULL = NULL est toujours aussi peu constructive...


On n'a pas ce problème avec minus : 


SQL>SELECT '+ap', a.*

  2   FROM tab_apres a

  3   MINUS

  4   SELECT '+ap', b.*

  5   FROM tab_avant b

  6   UNION ALL

  7   SELECT '+av', c.*

  8   FROM tab_avant c

  9   MINUS

 10   SELECT '+av', d.*

 11   FROM tab_apres d;


'+A          L          C

--- ---------- ----------

+ap          6

+ap          7

+av          1

+av          2


Elapsed: 00:00:00.04

 

Z'imaginez même pas quels trucs tordus j'étais allé chercher pour expliquer les différences...

Partager cet article

Published by Pacman - dans SQL
commenter cet article

commentaires