Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours 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 04/12/2010, 23h08   #1
Membre du Club
 
Inscription : mai 2008
Messages : 157
Détails du profil
Informations forums :
Inscription : mai 2008
Messages : 157
Points : 57
Points : 57
Par défaut Récupération de valeur de plusieurs tables

Bonsoir a tous,

j'ai 3 tables :
commandesclients
commandesSalle
Reglements

je cherche à afficher tous les montants des commandes d'un jour donné.
pour cela j'utilise la requête suivante :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
SELECT Reglements.MontantCB, Reglements.MontantChq, Reglements.MonatantEspeces, Reglements.MontantTR, Reglements.DateRglt, Reglements.FondCaisseDebut, Reglements.MontantGlobal, Reglements.Pourboire, Reglements.NumTable  
FROM Reglements, commandesclients, commandesclientssalle 
WHERE  Reglements.DateRglt = '20101125'  
  AND commandesclients.numcmd = reglements.numcmd  
  AND commandesclients.annulez = 0 
  AND commandesclients.impaye = 0 
GROUP BY reglements.numcmd, Reglements.MontantCB, Reglements.MontantChq, Reglements.MonatantEspeces, Reglements.MontantTR , Reglements.DateRglt, Reglements.FondCaisseDebut , Reglements.MontantGlobal,  Reglements.Pourboire,  Reglements.NumTable
 
UNION ALL 
 
SELECT Reglements.MontantCB, Reglements.MontantChq, Reglements.MonatantEspeces, Reglements.MontantTR, Reglements.DateRglt, Reglements.FondCaisseDebut, Reglements.MontantGlobal,  Reglements.Pourboire, Reglements.NumTable  
FROM Reglements, commandesclients, commandesclientssalle 
WHERE  Reglements.DateRglt = '20101125'  
  AND commandesclientssalle.numcmd = reglements.numcmd  
  AND commandesclientssalle.annulez = 0 
  AND commandesclientssalle.impaye = 0  
GROUP BY reglements.numcmd, Reglements.MontantCB, Reglements.MontantChq, Reglements.MonatantEspeces, Reglements.MontantTR, Reglements.DateRglt, 
Reglements.FondCaisseDebut, Reglements.MontantGlobal, Reglements.Pourboire,  
Reglements.NumTable   ORDER BY reglements.daterglt
tant que les 2 tables contiennent au moins un enregistrement ça marche, mais si par exemple, la table commandesclients est vide il n' y a aucun résultat

comment faire pour pouvoir afficher l'ensemble dans tous les cas ?
faut-il utiliser autre chose que union all

merci de votre aide je suis bloqué et je dois corriger mon bug rapidement
cdsoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/12/2010, 01h03   #2
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 957
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 10 957
Points : 18 165
Points : 18 165
Envoyer un message via MSN à CinePhil
La syntaxe normalisée depuis 1992 pour les jointures utilise l'opérateur JOIN. Dans votre cas, puisque toutes les lignes d'une tables ne semblent pas pouvoir être mises en correspondance avec l'autre, il vous faut une jointure externe (LEFT [ou RIGHT] OUTER JOIN).
En écrivant les jointures correctement, vous auriez vu qu'il manque une condition de jointure dans votre requête !

Un GROUP BY sans fonction de regroupement dans le SELECT, ça ne sert pas à grand chose, à part imiter le DISTINCT. En l'occurrence, votre requête ne répondra pas à votre besoin puisque vous voulez tous les montants de toutes les commandes.

En SQL, une date est normalement stockée dans une colonne de type DATE au format 'aaaa-mm-jj'.

Pourquoi faites-vous l'union de deux fois la même requête ?

Pourquoi faites vous dans la deuxième un ORDER BY reglements.daterglt alors que dans le WHERE vous ne retenez qu'une date ?

L'utilisation des alias et de l'indentation rendrait votre requête plus facile et agréable à lire.

Voici votre requête récrite.
Code :
1
2
3
4
5
6
7
SELECT r.MontantCB, r.MontantChq, r.MontantEspeces, r.MontantTR, r.DateRglt, r.FondCaisseDebut, r.MontantGlobal, r.Pourboire, r.NumTable
FROM Reglements AS r
INNER JOIN commandesClients AS cc ON cc.numcmd = r.numcmd
INNER JOIN commandesclientssalle AS ccs -- Manque une condition de jointure
WHERE r.DateRglt = '2010-11-25'
  AND cc.annulez = 0
  AND cc.impaye = 0
À vous de déterminer le sens de la jointure externe en remplaçant où il faut INNER par LEFT OUTER ou RIGHT OUTER.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2010, 16h22   #3
Membre du Club
 
Inscription : mai 2008
Messages : 157
Détails du profil
Informations forums :
Inscription : mai 2008
Messages : 157
Points : 57
Points : 57
merci pour votre explication
voici ce que j'ai donc fait en espérant d'avoir bien compris les nuances
Code :
1
2
3
4
5
6
7
8
9
10
 
SELECT r.MontantCB, r.MontantChq, r.MontantEspeces, r.MontantTR, r.DateRglt, r.FondCaisseDebut, r.MontantGlobal, r.Pourboire, r.NumTable
FROM Reglements AS r
LEFT OUTER JOIN commandesClients AS cc ON cc.numcmd = r.numcmd
LEFT OUTER JOIN commandesclientssalle AS ccs ON ccs.numcmd = r.numcmd
WHERE r.DateRglt = '2010-11-25'
  AND cc.annulez = 0
  AND cc.impaye = 0
AND ccs.annulez = 0
  AND ccs.impaye = 0
je marque ce post comme résolu, mais merci tout de même de me dire si c'est faux
A+
cdsoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2010, 17h29   #4
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 631
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 631
Points : 2 616
Points : 2 616
bonjour,

Vous avez mis dans votre where :
Code :
1
2
3
4
5
 
  AND cc.annulez = 0
  AND cc.impaye = 0
AND ccs.annulez = 0
  AND ccs.impaye = 0
Ceci va entrainer la transformation de vos left outer join en inner join.

Si vous voulez gardez des left outer join il faudra plutôt utiliser ce genre de syntaxe.


Code :
1
2
3
4
5
6
 
SELECT r.MontantCB, r.MontantChq, r.MontantEspeces, r.MontantTR, r.DateRglt, r.FondCaisseDebut, r.MontantGlobal, r.Pourboire, r.NumTable
FROM Reglements AS r
LEFT OUTER JOIN commandesClients AS cc ON cc.numcmd = r.numcmd AND cc.annulez = 0 AND cc.impaye = 0
LEFT OUTER JOIN commandesclientssalle AS ccs ON ccs.numcmd = r.numcmd AND ccs.annulez = 0 AND ccs.impaye = 0
WHERE r.DateRglt = '2010-11-25'
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/12/2010, 17h34   #5
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 957
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 10 957
Points : 18 165
Points : 18 165
Envoyer un message via MSN à CinePhil
Citation:
Envoyé par cdsoft Voir le message
voici se que j'ai donc fait en espérant d'avoir bien compris les nuances
Code :
1
2
3
4
5
6
7
8
9
10
 
SELECT r.MontantCB, r.MontantChq, r.MontantEspeces, r.MontantTR, r.DateRglt, r.FondCaisseDebut, r.MontantGlobal, r.Pourboire, r.NumTable
FROM Reglements AS r
LEFT OUTER JOIN commandesClients AS cc ON cc.numcmd = r.numcmd
LEFT OUTER JOIN commandesclientssalle AS ccs ON ccs.numcmd = r.numcmd
WHERE r.DateRglt = '2010-11-25'
  AND cc.annulez = 0
  AND cc.impaye = 0
AND ccs.annulez = 0
  AND ccs.impaye = 0
je marque ce post comme résolu, mais merci tout de même de me dire si s'est faux
Tu fais des jointures externes à gauche et tu poses des restrictions (dans le WHERE) sur les tables de droite. Résultat : Tu as fait des jointures internes !

Explication avec un exemple simple...
Soit les tables suivantes :
Table A
idA, valA
1, 'toto'
2, 'titi'
3, 'tata'

Table B
idB, idA, valB, booleen
1, 2, 'riri', 0
2, 3, 'fifi', 1

Faisons une jointure externe à gauche sans condition :
Code :
1
2
3
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen
FROM A
LEFT OUTER JOIN B ON B.idA = A.idA
=> Résultat :
idA, valA, idB, valB, booleen
1, 'toto', NULL, NULL, NULL
2, 'titi', 1, 'riri', 0
3, 'tata', 2, 'fifi', 1

Ajoutons une restriction dans le WHERE sur la table B :
Code :
1
2
3
4
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen
FROM A
LEFT OUTER JOIN B ON B.idA = A.idA
WHERE B.booleen = 1
=> Résultat :
idA, valA, idB, valB, booleen
3, 'tata', 2, 'fifi', 1

La seule ligne qui répond à la condition est celle de fifi. On n'a plus toutes les lignes de A.
J'aurais obtenu le même résultat avec une jointure interne.
1ère requête sans WHERE
Code :
1
2
3
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen
FROM A
INNER JOIN B ON B.idA = A.idA
=> Résultat :
idA, valA, idB, valB, booleen
2, 'titi', 1, 'riri', 0
3, 'tata', 2, 'fifi', 1

2ème requête avec le WHERE :
Code :
1
2
3
4
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen
 FROM A
 LEFT OUTER JOIN B ON B.idA = A.idA
WHERE B.booleen = 1
=> Résultat :
idA, valA, idB, valB, booleen
3, 'tata', 2, 'fifi', 1

Reprenons maintenant la jointure externe et mettons la restriction dans la clause de jointure :
Code :
1
2
3
4
SELECT A.idA, A.valA, B.idB, B.valB, B.booleen
 FROM A
 LEFT OUTER JOIN B ON B.idA = A.idA
  AND B.booleen = 1
=> Résultat :
idA, valA, idB, valB, booleen
1, 'toto', NULL, NULL, NULL
2, 'titi', NULL, NULL, NULL
3, 'tata', 2, 'fifi', 1

La jointure est faite sur les données restreintes au booleen = 1, c'est à dire seulement fifi mais les lignes de A sont affichées avec NULL dans les colonnes de B quand il n'y a pas de correspondance.

Conclusion :
Avec une jointure externe, il faut déplacer les conditions de restriction de la table externe du WHERE vers la condition de jointure. Sinon c'est l'équivalent d'une jointure interne.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 08/12/2010, 17h26   #6
Membre du Club
 
Inscription : mai 2008
Messages : 157
Détails du profil
Informations forums :
Inscription : mai 2008
Messages : 157
Points : 57
Points : 57
bonjour,

Super et merci car vos explications sont claires.

A+
cdsoft 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 09h33.


 
 
 
 
Partenaires

Hébergement Web