2016-11-24 1 views
2

J'ai une requête non ansi complexe et j'ai besoin de convertir en requête ansi.Convertir la jointure externe Oracle héritée en Ansi SQL

alors je vais prendre un petit exemple pour décrire mon problème

entrée requête

SELECT a.name, 
     a.empno, 
     b.loc, 
     c.inr 
    FROM a, 
     b, 
     c 
    WHERE a.deptno = b.deptno(+) 
    AND b.empno(+) = 190 
    a.deptno = c.deptno(+) 
    AND c.empno(+) = 190; 

Merci à l'avance

+0

MySQL et SQL Server et Oracle? Lesquels utilisez-vous ici?requête d'entrée – jarlh

+0

est d'oracle –

+0

êtes-vous vraiment auto-joindre à la même table deux fois, ou sont ces trois tableaux différents? – Boneist

Répondre

2

Votre requête est équivalente à la requête conforme ci-dessous ANSI:

SELECT a.name, 
     a.empno, 
     b.loc, 
     c.inr 
FROM tab a 
LEFT JOIN tab b ON a.deptno = b.deptno AND b.empno = 190 
LEFT JOIN tab c ON a.deptno = c.deptno AND c.empno = 190;   

Vous devez placer les prédicats b.empno = 190 et c.empno = 190 à l'intérieur des clauses ON des opérations LEFT JOIN, sinon LEFT JOIN devient un INNER JOIN.

+0

mais a.deptno = b.deptno (+) cela signifie qu'il devrait y avoir quitté la jointure externe –

+0

ne me dérange pas, je me réfère à ce lien où il montre qu'il devrait être laissé http: // stackoverflow. com/questions/19905028/what-is-différence entre-ansi-et-non-ansi-joint et-qui-do-you-recommandez –

+0

@KishoreKumarSuthar OK, je ne savais pas à ce sujet. S'il vous plaît vérifier la modification que j'ai faite. –

3

(NB Ceci n'est pas une réponse, car il semble que la réponse de Giorgos soit ce que vous recherchiez vraiment, mais il est trop long de faire un commentaire Je voulais m'assurer que vous compreniez pourquoi votre requête originale n'est pas faire ce que (je pense) vous pensez que c'est)

Votre requête originale finit par faire une jointure interne, parce que vous demandez des valeurs spécifiques pour les colonnes b.empno et c.empno sans les inclure dans la gauche jointure externe. C'est à dire. vous dites: "premièrement, joignez la jointure externe b à a, et ensuite, filtrez les lignes qui n'ont pas de b.empno = 190". Cela va se débarrasser de toutes les lignes où b.empno est nulle ainsi que d'autres valeurs de b.empno.

Voici un exemple simple montrant les différents comportements:

style ancien jointure externe gauche avec externe non left join filtre:

WITH t1 AS (SELECT 1 ID, 10 val FROM dual UNION ALL 
      SELECT 2 ID, 20 val FROM dual UNION ALL 
      SELECT 3 ID, 30 val FROM dual), 
    t2 AS (SELECT 1 ID, 100 val FROM dual UNION ALL 
      SELECT 1 ID, 150 val FROM dual UNION ALL 
      SELECT 2 ID, 200 val FROM dual UNION ALL 
      SELECT 2 ID, 250 val FROM dual) 
SELECT t1.id, t1.val, t2.val 
FROM t1, 
     t2 
WHERE t1.id = t2.id(+) 
AND t2.val = 200 
ORDER BY t1.id, t2.val; 

     ID  VAL  VAL 
---------- ---------- ---------- 
     2   20  200 

style ancien jointure avec filtre:

WITH t1 AS (SELECT 1 ID, 10 val FROM dual UNION ALL 
      SELECT 2 ID, 20 val FROM dual UNION ALL 
      SELECT 3 ID, 30 val FROM dual), 
    t2 AS (SELECT 1 ID, 100 val FROM dual UNION ALL 
      SELECT 1 ID, 150 val FROM dual UNION ALL 
      SELECT 2 ID, 200 val FROM dual UNION ALL 
      SELECT 2 ID, 250 val FROM dual) 
SELECT t1.id, t1.val, t2.val 
FROM t1, 
     t2 
WHERE t1.id = t2.id 
AND t2.val = 200 
ORDER BY t1.id, t2.val; 

     ID  VAL  VAL 
---------- ---------- ---------- 
     2   20  200 

Vous pouvez voir que les résultats des deux requêtes ci-dessus sont identique, ce qui signifie que la première requête avec les jointures externes de gauche fait vraiment une jointure interne. Et la syntaxe de jointure ANSI requête équivalente à ce serait:

intérieure ANSI style jointure avec filtre:

WITH t1 AS (SELECT 1 ID, 10 val FROM dual UNION ALL 
      SELECT 2 ID, 20 val FROM dual UNION ALL 
      SELECT 3 ID, 30 val FROM dual), 
    t2 AS (SELECT 1 ID, 100 val FROM dual UNION ALL 
      SELECT 1 ID, 150 val FROM dual UNION ALL 
      SELECT 2 ID, 200 val FROM dual UNION ALL 
      SELECT 2 ID, 250 val FROM dual) 
SELECT t1.id, t1.val, t2.val 
FROM t1 
     INNER JOIN t2 ON t1.id = t2.id 
WHERE t2.val = 200; 

     ID  VAL  VAL 
---------- ---------- ---------- 
     2   20  200 

Vous pouvez voir la différence des résultats en incluant la colonne filtrée dans la jointure externe dans la requête ancienne d'origine:

style ancien jointure externe gauche avec jointure externe gauche filtre

WITH t1 AS (SELECT 1 ID, 10 val FROM dual UNION ALL 
      SELECT 2 ID, 20 val FROM dual UNION ALL 
      SELECT 3 ID, 30 val FROM dual), 
    t2 AS (SELECT 1 ID, 100 val FROM dual UNION ALL 
      SELECT 1 ID, 150 val FROM dual UNION ALL 
      SELECT 2 ID, 200 val FROM dual UNION ALL 
      SELECT 2 ID, 250 val FROM dual) 
SELECT t1.id, t1.val, t2.val 
FROM t1, 
     t2 
WHERE t1.id = t2.id(+) 
AND t2.val(+) = 200 
ORDER BY t1.id, t2.val; 

     ID  VAL  VAL 
---------- ---------- ---------- 
     1   10 
     2   20  200 
     3   30 

Et, selon la réponse de Giorgos, la norme ANSI équivalente syntaxe de jointure requête serait:

style ANSI jointure externe avec filtre de jointure externe:

WITH t1 AS (SELECT 1 ID, 10 val FROM dual UNION ALL 
      SELECT 2 ID, 20 val FROM dual UNION ALL 
      SELECT 3 ID, 30 val FROM dual), 
    t2 AS (SELECT 1 ID, 100 val FROM dual UNION ALL 
      SELECT 1 ID, 150 val FROM dual UNION ALL 
      SELECT 2 ID, 200 val FROM dual UNION ALL 
      SELECT 2 ID, 250 val FROM dual) 
SELECT t1.id, t1.val, t2.val 
FROM t1 
     left OUTER JOIN t2 ON t1.id = t2.id AND t2.val = 200 
ORDER BY t1.id, t2.val; 

     ID  VAL  VAL 
---------- ---------- ---------- 
     1   10 
     2   20  200 
     3   30 
+0

pouvez-vous s'il vous plaît faire la requête finale pour la requête d'entrée donné. Je suis peu confus en voyant beaucoup de réponses. –

+0

Je vous ai donné des exemples que vous pouvez vous courir pour voir quelles sont les différences entre les différentes jointures sont. vous ne nous avez pas donné de données d'échantillons ou résultats attendus pour aller plus loin, il est donc difficile pour nous de dire à coup sûr ce que vous voulez que votre requête à faire. Ma réponse ne se veut pas une réponse directe à votre question, il est censé vous donner quelques informations afin que vous puissiez apprendre quelque chose et j'espère l'appliquer à votre propre situation vous-même. – Boneist

+0

J'ai pris juste un exemple. J'ai une requête complexe. J'ai modifié la requête. Est-ce que 1) est correct pour la requête d'entrée donnée? –