Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/10/2005, 09h47   #1
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
Par défaut Requette PL/SQL - Oracle 8i

Bjr,

J'ai un petit pb en PL/SQL, j'ai une requette avec cette jointure

AND e2.val_rub = a.mot_fin_per

Dans certain cas a.mot_fin_per est NULL et j'aurais besoin de sortir aussi ces enregistrements, mais je ne trouve pas comment faire

Avec vous des idées ?

Merci
rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 09h50   #2
Inactif
 
Avatar de Médiat
 
Inscription : décembre 2003
Messages : 1 946
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 1 946
Points : 1 932
Points : 1 932
La jointure externe est sans doute la solution à ton problème, mais il faudrait en dire un peur plus (ne serait-ce que la version que tu utilises)
Médiat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 09h56   #3
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
Merci mais j'avais essayé la jointure externe, mais çà ne marche pas

J'utilise Oracle 8i

Et voici mon script
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
SELECT DISTINCT a.struc_dads periode, a.dat_debut datdeb,
a.mot_deb_per motdeb ,e1.lib_rub libmotdeb,
a.dat_fin datfin,
a.mot_fin_per motfin, e2.lib_rub libmotfin ,
a.ind_valorise valorisation,
c.num_employ, c.nom_employ, a.idf_agent, d.nom_usuel, d.nom_prenom, d.num_insee,
 d.cle_insee
FROM gp.tdu_agtmot a, gp.emploi b, gp.employ c, gp.agtnat d,
gp.rub_ref e1, gp.rub_ref e2
WHERE a.num_employ = '01'
AND c.num_employ = a.num_employ
AND a.dat_debut >= '01/01/2005'
/*AND a.dat_fin >= '01/01/2005'*/
AND d.nom_usuel BETWEEN 'A' AND 'C'
AND a.idf_agent = d.idf_agent
AND a.idf_agent = b.idf_agent
AND d.num_grpaie ='4'
AND a.struc_dads = 'S41'
AND e1.cod_rub = 'S41.G01.00.002'
AND e1.val_rub = a.mot_deb_per
AND e2.cod_rub = 'S41.G01.00.004'
AND (e2.val_rub  = a.mot_fin_per (+)) 
AND a.idf_agent = '1202'
ORDER BY a.idf_agent, d.nom_usuel, c.nom_employ, a.struc_dads, a.dat_debut, a.dat_fin, a.mot_deb_per, a.mot_fin_per
rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 10h13   #4
Inactif
 
Avatar de Médiat
 
Inscription : décembre 2003
Messages : 1 946
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 1 946
Points : 1 932
Points : 1 932
Pense à indenter correctement ta requête en exemple, voici le minimum :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
SELECT DISTINCT a.struc_dads periode, a.dat_debut datdeb, 
                a.mot_deb_per motdeb ,e1.lib_rub libmotdeb, 
                a.dat_fin datfin, 
                a.mot_fin_per motfin, e2.lib_rub libmotfin , 
                a.ind_valorise valorisation, 
                c.num_employ, c.nom_employ, a.idf_agent, d.nom_usuel, 
                d.nom_prenom, d.num_insee, d.cle_insee 
FROM gp.tdu_agtmot a, gp.emploi b, gp.employ c, gp.agtnat d, 
     gp.rub_ref e1, gp.rub_ref e2 
WHERE a.num_employ = '01' 
  AND c.num_employ = a.num_employ 
  AND a.dat_debut >= '01/01/2005' 
  /*AND a.dat_fin >= '01/01/2005'*/ 
  AND d.nom_usuel BETWEEN 'A' AND 'C' 
  AND a.idf_agent = d.idf_agent 
  AND a.idf_agent = b.idf_agent 
  AND d.num_grpaie ='4' 
  AND a.struc_dads = 'S41' 
  AND e1.cod_rub = 'S41.G01.00.002' 
  AND e1.val_rub = a.mot_deb_per 
  AND e2.cod_rub = 'S41.G01.00.004' 
  AND (e2.val_rub  = a.mot_fin_per (+)) 
  AND a.idf_agent = '1202' 
ORDER BY a.idf_agent, d.nom_usuel, c.nom_employ, a.struc_dads,
         a.dat_debut, a.dat_fin, a.mot_deb_per, a.mot_fin_per
Je me plantais toujours sur le côté où mettre le (+) (vive la syntaxe standard ), es-tu sur que tu l'a mise du bon côté ?
Il faut ajouter le (+) partout ou ta table apparaît, par exemple si la jointure ne peut pas se faire sur le table e2, il est impossible que e2.cod_rub = 'S41.G01.00.004', puisque e2.cod_rub est NULL
Médiat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 10h26   #5
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
Citation:
Envoyé par Médiat
Je me plantais toujours sur le côté où mettre le (+) (vive la syntaxe standard ), es-tu sur que tu l'a mise du bon côté ?
Il faut ajouter le (+) partout ou ta table apparaît, par exemple si la jointure ne peut pas se faire sur le table e2, il est impossible que e2.cod_rub = 'S41.G01.00.004', puisque e2.cod_rub est NULL
pour ta réponse !

Désolé pour l'indentation

Pour ce qui est du code, en fait c'est 'a.mot_fin_per' qui peut-être vide, la table e2 n'est jamais vide car c'est juste une table permettant de faire la correspondante en un code rubrique et un libellé

Je rame très fort en ce lundi matin
rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 10h48   #6
Inactif
 
Avatar de Médiat
 
Inscription : décembre 2003
Messages : 1 946
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 1 946
Points : 1 932
Points : 1 932
Citation:
Envoyé par rjulie
Pour ce qui est du code, en fait c'est 'a.mot_fin_per' qui peut-être vide, la table e2 n'est jamais vide car c'est juste une table permettant de faire la correspondante en un code rubrique et un libellé
C'est parce que 'a.mot_fin_per' est NULL que tu n'as pas de lien sur e2, et donc e2.cod_rub est NULL (e2 ne pointe sur rien).
Médiat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 10h52   #7
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
Citation:
Envoyé par Médiat
[C'est parce que 'a.mot_fin_per' est NULL que tu n'as pas de lien sur e2, et donc e2.cod_rub est NULL (e2 ne pointe sur rien).
Exact, mais bon je vois pas comment me sortir de ce pb

rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 10h57   #8
Expert Confirmé
 
Homme
Chef de projet en SSII
Inscription : janvier 2004
Messages : 2 866
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Chef de projet en SSII
Secteur : Conseil

Informations forums :
Inscription : janvier 2004
Messages : 2 866
Points : 3 448
Points : 3 448
Citation:
Envoyé par Médiat
C'est parce que 'a.mot_fin_per' est NULL que tu n'as pas de lien sur e2, et donc e2.cod_rub est NULL (e2 ne pointe sur rien).
Euh, j'aurais plutôt dit que le problème venait de ces conditions :
Code :
1
2
3
4
5
AND a.dat_debut >= '01/01/2005' 
  /*AND a.dat_fin >= '01/01/2005'*/ 
AND d.nom_usuel BETWEEN 'A' AND 'C' 
AND a.idf_agent = d.idf_agent 
AND a.idf_agent = b.idf_agent
Car s'il ne trouve pas de a.mot_fin_per, il ne peut pas faire la jointure avec les tables b et d.

Voici un post qui devrait t'aider à trouver une solution :
http://www.developpez.net/forums/viewtopic.php?t=406724&sid=483afbb75e4783f6ce84e955fa27c375
__________________
Un problème sans solution est un problème mal posé

Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
plaineR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 11h09   #9
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
Citation:
Envoyé par plaineR
Voici un post qui devrait t'aider à trouver une solution :
http://www.developpez.net/forums/viewtopic.php?t=406724&sid=483afbb75e4783f6ce84e955fa27c375

Merci, j'avais vu ta solution, je suis en train d'essayer de l'appliquer, mais c'est pas gagné
rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 11h23   #10
Inactif
 
Avatar de Médiat
 
Inscription : décembre 2003
Messages : 1 946
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 1 946
Points : 1 932
Points : 1 932
Citation:
Envoyé par plaineR
Euh, j'aurais plutôt dit que le problème venait de ces conditions :
Code :
1
2
3
4
5
AND a.dat_debut >= '01/01/2005' 
  /*AND a.dat_fin >= '01/01/2005'*/ 
AND d.nom_usuel BETWEEN 'A' AND 'C' 
AND a.idf_agent = d.idf_agent 
AND a.idf_agent = b.idf_agent
Car s'il ne trouve pas de a.mot_fin_per, il ne peut pas faire la jointure avec les tables b et d.
Je ne comprends pas : a.mot_fin_per à NULL ne veut pas dire que l'enregistrement n'existe pas, donc a.idf_agent peut très bien exister, et donc la jointure sur b et d se passer très bien, ce qui n'est pas le cas de la jointure sur e2 qui se fait au travers de ce fameux a.mot_fin_per ?
Médiat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 11h28   #11
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
Citation:
Envoyé par Médiat
Je ne comprends pas : a.mot_fin_per à NULL ne veut pas dire que l'enregistrement n'existe pas, donc a.idf_agent peut très bien exister, et donc la jointure sur b et d se passer très bien, ce qui n'est pas le cas de la jointure sur e2 qui se fait au travers de ce fameux a.mot_fin_per ?
Celà me semble beaucoup plus logique, en effet j'ai bien un enregistrement a.idf_agent, mais par contre je n'arrive pas à faire la liaison avec a.mot_fin_per qui est à NULL :-(

Et je vois pas comment contourner le pb
rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 11h43   #12
Inactif
 
Avatar de Médiat
 
Inscription : décembre 2003
Messages : 1 946
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 1 946
Points : 1 932
Points : 1 932
Voila comment je ferais avec la syntaxe normée :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT DISTINCT a.struc_dads periode, a.dat_debut datdeb, 
                a.mot_deb_per motdeb ,e1.lib_rub libmotdeb, 
                a.dat_fin datfin, 
                a.mot_fin_per motfin, e2.lib_rub libmotfin , 
                a.ind_valorise valorisation, 
                c.num_employ, c.nom_employ, a.idf_agent, d.nom_usuel, 
                d.nom_prenom, d.num_insee, d.cle_insee 
FROM gp.tdu_agtmot a INNER JOIN gp.emploi b        ON a.idf_agent  = b.idf_agent
                     INNER JOIN gp.employ c        ON c.num_employ = a.num_employ
                     INNER JOIN gp.agtnat d        ON a.idf_agent  = d.idf_agent
                     INNER JOIN gp.rub_ref e1      ON e1.val_rub   = a.mot_deb_per
                     LEFT OUTER JOIN gp.rub_ref e2 ON e2.val_rub   = a.mot_fin_per AND e2.cod_rub = 'S41.G01.00.004'
WHERE a.num_employ = '01' 
  AND a.dat_debut >= '01/01/2005' 
  /*AND a.dat_fin >= '01/01/2005'*/ 
  AND d.nom_usuel BETWEEN 'A' AND 'C' 
  AND d.num_grpaie ='4' 
  AND a.struc_dads = 'S41' 
  AND e1.cod_rub = 'S41.G01.00.002' 
  AND a.idf_agent = '1202' 
ORDER BY a.idf_agent, d.nom_usuel, c.nom_employ, a.struc_dads, 
         a.dat_debut, a.dat_fin, a.mot_deb_per, a.mot_fin_per
Les INNER JOIN sont faciles à traduire, le LEFT OUTER JOIN un peu moins (je ne sais jamais de quel côté mettre le (+).

Le point le plus important est la présence de e2.cod_rub = 'S41.G01.00.004' dans le ON du LEFT OUTER JOIN et non dans le WHERE.
c'est à dire :
e2.cod_rub(+) = 'S41.G01.00.004'
ou (je me plante tout le temps)
e2.cod_rub = 'S41.G01.00.004'(+)
Médiat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 11h51   #13
Expert Confirmé
 
Homme
Chef de projet en SSII
Inscription : janvier 2004
Messages : 2 866
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Chef de projet en SSII
Secteur : Conseil

Informations forums :
Inscription : janvier 2004
Messages : 2 866
Points : 3 448
Points : 3 448
Citation:
Envoyé par Médiat
Je ne comprends pas : a.mot_fin_per à NULL ne veut pas dire que l'enregistrement n'existe pas, donc a.idf_agent peut très bien exister, et donc la jointure sur b et d se passer très bien, ce qui n'est pas le cas de la jointure sur e2 qui se fait au travers de ce fameux a.mot_fin_per ?
Non, non, voici un petit exemple pour illustrer mes propos :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SQL> CREATE TABLE a (col1 varchar2(30), col2 varchar2(30));
TABLE created.
 
SQL> CREATE TABLE b (col1 varchar2(30), col2 varchar2(30));
TABLE created.
 
SQL> INSERT INTO a VALUES ('a', 'A');
1 row created.
 
SQL> INSERT INTO a VALUES ('b', 'B');
1 row created.
 
SQL> INSERT INTO b VALUES ('a', '1');
1 row created.
 
SQL> SELECT a.*, b.*
  2  FROM a, b
  3  WHERE a.col1 = b.col1 (+);
 
COL1 COL2 COL1 COL2
---- ---- ---- ----
a    A    a    1
b    B
Quand tu fais une jointure externe, c'est toutes les autres colonnes de la table du côté où est la jointure externe qui sont nulles et non les colonnes de l'autre table

Dans le cas de rjulie, la jointure avec les table b et d ne peut pas se faire si la jointure externe entre a et e ne sa fait pas puisque dans ce cas toutes le colonnes de a sont null.

[EDIT] La remarque que je fais plus haut est par rapport à la requête que rjulie a écrite qui me semble d'ailleurs fausse, je ferais plutôt quelque chose comme cela :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
SELECT DISTINCT a.struc_dads periode, a.dat_debut datdeb, 
                a.mot_deb_per motdeb ,e1.lib_rub libmotdeb, 
                a.dat_fin datfin, 
                a.mot_fin_per motfin, e2.lib_rub libmotfin , 
                a.ind_valorise valorisation, 
                c.num_employ, c.nom_employ, a.idf_agent, d.nom_usuel, 
                d.nom_prenom, d.num_insee, d.cle_insee 
FROM gp.tdu_agtmot a, gp.emploi b, gp.employ c, gp.agtnat d, 
     gp.rub_ref e1, gp.rub_ref e2 
WHERE a.num_employ = '01' 
  AND c.num_employ = a.num_employ 
  AND a.dat_debut >= '01/01/2005' 
  /*AND a.dat_fin >= '01/01/2005'*/ 
  AND d.nom_usuel BETWEEN 'A' AND 'C' 
  AND a.idf_agent = d.idf_agent 
  AND a.idf_agent = b.idf_agent 
  AND d.num_grpaie ='4' 
  AND a.struc_dads = 'S41' 
  AND e1.cod_rub = 'S41.G01.00.002' 
  AND e1.val_rub = a.mot_deb_per 
  AND e2.cod_rub(+) = 'S41.G01.00.004' 
  AND (e2.val_rub(+)  = a.mot_fin_per) 
  AND a.idf_agent = '1202' 
ORDER BY a.idf_agent, d.nom_usuel, c.nom_employ, a.struc_dads, 
         a.dat_debut, a.dat_fin, a.mot_deb_per, a.mot_fin_per
[/EDIT]
__________________
Un problème sans solution est un problème mal posé

Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
plaineR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 12h01   #14
Inactif
 
Avatar de Médiat
 
Inscription : décembre 2003
Messages : 1 946
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 1 946
Points : 1 932
Points : 1 932
PlaineR >> tu me fais soupçonner de plus en plus que je ne suis pas le seul à ne pas me rappeler de quel côté mettre le (+), et que je partage ce handicap avec rjulie
La réponse serait alors dans :

Code :
1
2
AND e2.cod_rub(+) = 'S41.G01.00.004' 
AND e2.val_rub(+)  = a.mot_fin_per
Je ne peux pas faire de test avant ce soir, pourrais-tu (si tu as le temps ) ajouter une ligne dans la table a et ré-exécuter ton SELECT

insert into a values (NULL, 'C');

si je ne me trompe pas trop, tu devrais trouver :
Code :
1
2
3
4
5
COL1 COL2 COL1 COL2 
---- ---- ---- ---- 
a    A    a    1 
b    B
     C

[EDIT]
Nous sommes d'accord
Laisse tomber le test
[/EDIT]
Médiat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2005, 12h40   #15
Invité de passage
 
Inscription : septembre 2005
Messages : 18
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 18
Points : 3
Points : 3
pour vos réponses

La solution est la suivante :
Code :
1
2
3
 
AND e2.cod_rub (+) = 'S41.G01.00.004'
AND e2.val_rub (+) = mot_fin_per
La morale de cette histoire c'est que je risque de me planter encore longtemps avec les (+)

Merci encore
rjulie est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 05h02.


 
 
 
 
Partenaires

Hébergement Web