Voici une bien étrangère limitation que nous offre l’optimiseur de PostgreSQL. Il n’est en effet pas capable de faire une jointure externe bilatérale lorsque le prédicat de jointure n’est pas « sargeable »…
La jointure externe est assez peu utilisée, mais elle se conçoit bien, lorsque l’on veut pas exemple faire du rapprochement de données; En voici un exemple :
Soit deux tables contenant des clients pour l’un et des prospects pour l’autre. On à collecté comme information le n° de SIREN et le nom d’enseigne.
Mais le nom peut être mal orthographié comme le SIREN peut être incorrect. Le but étant de joindre ces données avec le maximum de « chances »…
Voici le modèle de la base :
(CLI_ID INT PRIMARY KEY,
CLI_SIREN CHAR(9) NOT NULL UNIQUE,
CLI_ENSEIGNE VARCHAR(16) NOT NULL);
CREATE TABLE T_PROSPECT_PSP
(PSP_ID INT PRIMARY KEY,
PSP_SIREN CHAR(9) NOT NULL UNIQUE,
PSP_ENSEIGNE VARCHAR(16) NOT NULL);
Et quelques données de test :
(1, '123456789', 'IBM'),
(2, '111111111', 'Microsoft'),
(3, '999555111', 'SAP');
INSERT INTO T_PROSPECT_PSP VALUES
(101, '123456789', 'IBM'),
(102, '555555555', 'Microsoft'),
(103, '777777777', 'Amazon'),
(104, '444444444', 'Google');
Nous voyons que le code SIREN de Microsoft ne se recoupe pas sur les deux tables… Cepandant nous voulons toutes les données des deux tables avec jointure sur le code SIREN ou à défaut sur le nom.
La requête suivante correspond à cette demande :
FROM T_CLIENT_CLI AS C
FULL OUTER JOIN T_PROSPECT_PSP AS P
ON C.CLI_SIREN = P.PSP_SIREN
OR C.CLI_ENSEIGNE = P.PSP_ENSEIGNE
Voici ce qu’elle donne sous MS SQL Server :
CLI_ID CLI_SIREN CLI_ENSEIGNE PSP_ID PSP_SIREN PSP_ENSEIGNE ----------- --------- ---------------- ----------- --------- ---------------- 1 123456789 IBM 101 123456789 IBM 2 111111111 Microsoft 102 555555555 Microsoft 3 999555111 SAP NULL NULL NULL NULL NULL NULL 103 777777777 Amazon NULL NULL NULL 104 444444444 Google
Hélas, cette requête ne passe pas sous aucune version de PostGreSQL. le message est le suivant :
ERREUR: FULL JOIN est supporté seulement avec les conditions de jointures MERGE et de jointures HASH JOIN ********** Erreur ********** État SQL :0A000
L’explication est la suivante :
PostGreSQL veut impérativement que la jointure soir « sargeable », c’est à dire utiliser une technique de jointure avec algorithme MERGE (fusion d’un tri resultant d’index) ou algorithme HASH (donc index avec clef de hachage)… Or, avec un « ou » (OR) dans la clause On de la jointure il n’y a pas de « sargeabilité » possible !
Si vous ne prenez pas en compte la dernière ligne (OR OR C.CLI_ENSEIGNE = P.PSP_ENSEIGNE) alors la requête s’exécute. Si vous mettez AND à la place de OR, ça passe. mais tout ceci ne donne pas le même résultat
En fait, c’est une limitation assez curieuse de l’optimiseur de PostGreSQL qui interdit le FULL OUTER JOIN dans certains cas…
Évidemment, cela constitue à l’évidence un bug…
PS : version PG testée 9.1.2 et 9.3.4
Expert S.G.B.D relationnelles et langage S.Q.L
Moste Valuable Professionnal Microsoft SQL Server
Société SQLspot : modélisation, conseil, formation,
optimisation, audit, tuning, administration SGBDR
Enseignant: CNAM PACA, ISEN Toulon, CESI Aix en Prov.
L’entreprise SQL Spot
Le site web sur le SQL et les SGBDR