Grosse galère dans un LEFT JOIN
Résolu/Fermé
heliconius
Messages postés
539
Date d'inscription
mardi 1 juillet 2008
Statut
Membre
Dernière intervention
23 juin 2023
-
Modifié le 22 juil. 2019 à 16:44
Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 - 23 juil. 2019 à 08:37
Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 - 23 juil. 2019 à 08:37
A voir également:
- Grosse galère dans un LEFT JOIN
- Comment enregistrer un brouillon instagram dans sa galerie - Guide
- Cents = gettens(left(mid(mynumber, decimalplace + 1) & _ "00", 2)) ✓ - Forum Excel
- Left shift clavier - Forum Windows 10
- Supprimer photo dans fichier et galerie mais pas dans carte sd ✓ - Forum Samsung
- Comment masquer une photo dans la galerie - Guide
4 réponses
Reivax962
Messages postés
3672
Date d'inscription
jeudi 16 juin 2005
Statut
Membre
Dernière intervention
11 février 2021
1 011
22 juil. 2019 à 18:18
22 juil. 2019 à 18:18
Bonjour,
En partant du principe que pour chaque facture, on souhaite voir chaque personne en face, je t'invite à regarder la clause CROSS JOIN qui relie chaque ligne d'une table à chaque ligne d'une autre.
Ainsi,
te donne un bon point de départ.
Ensuite, il suffira de joindre en LEFT OUTER JOIN les paiements, et le tour est joué !
Là tu as presque ce que tu veux, mais il y a des lignes en trop, celles qui concernent les factures individuelles. C'est facilement réglé avec un petit WHERE :
Voilà, j'espère que ça te convient :)
Xavier
En partant du principe que pour chaque facture, on souhaite voir chaque personne en face, je t'invite à regarder la clause CROSS JOIN qui relie chaque ligne d'une table à chaque ligne d'une autre.
Ainsi,
SELECT * FROM fct_Factures f CROSS JOIN fct_Personnes pe
te donne un bon point de départ.
Ensuite, il suffira de joindre en LEFT OUTER JOIN les paiements, et le tour est joué !
SELECT * FROM fct_Factures f CROSS JOIN fct_Personnes pe LEFT OUTER JOIN fct_Payer pa ON pe.idpers = pa.idpers AND pa.idfact = f.idfact ORDER BY f.idfact
Là tu as presque ce que tu veux, mais il y a des lignes en trop, celles qui concernent les factures individuelles. C'est facilement réglé avec un petit WHERE :
SELECT * FROM fct_Factures f CROSS JOIN fct_Personnes pe LEFT OUTER JOIN fct_Payer pa ON pe.idpers = pa.idpers AND pa.idfact = f.idfact WHERE f.idtype=2 OR (f.idtype=1 AND pa.idfact IS NOT NULL) ORDER BY f.idfact
Voilà, j'espère que ça te convient :)
Xavier
yg_be
Messages postés
23399
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
17 décembre 2024
Ambassadeur
1 556
Modifié le 22 juil. 2019 à 16:55
Modifié le 22 juil. 2019 à 16:55
bonjour, moi j'essaierais avec un deuxième LEFT JOIN.
ce serait plus clair pour nous si, dans le SELECT, tu mettais le nom de la table avant chaque champ. sinon il nous faut analyser les autres informations.
ce serait plus clair pour nous si, dans le SELECT, tu mettais le nom de la table avant chaque champ. sinon il nous faut analyser les autres informations.
SELECT fa.idfact,datfact,numfact,objet,totfact,idtype,pe.idpers,prenom,datpay,montant FROM fct_Personnes AS pe LEFT JOIN fct_Payer AS pa ON pe.idpers=pa.idpers LEFT JOIN fct_Factures AS fa ON pa.idfact=fa.idfact ORDER BY pa.idfact,pe.idpers
heliconius
Messages postés
539
Date d'inscription
mardi 1 juillet 2008
Statut
Membre
Dernière intervention
23 juin 2023
139
22 juil. 2019 à 18:20
22 juil. 2019 à 18:20
Je viens d'essayer... :
mysql> SELECT fa.idfact,datfact,numfact,objet,totfact,idtype,pe.idpers,prenom,datpay,montant -> FROM fct_Personnes AS pe LEFT JOIN fct_Payer AS pa ON pe.idpers=pa.idpers -> LEFT JOIN fct_Factures AS fa ON pa.idfact=fa.idfact -> ORDER BY pa.idfact,pe.idpers; +--------+------------+---------+----------+---------+--------+--------+--------+------------+---------+ | idfact | datfact | numfact | objet | totfact | idtype | idpers | prenom | datpay | montant | +--------+------------+---------+----------+---------+--------+--------+--------+------------+---------+ | NULL | NULL | NULL | NULL | NULL | NULL | 3 | Anne | NULL | NULL | | 1 | 2019-03-27 | | EDF | 171.25 | 2 | 1 | Gwenn | 2019-05-03 | 72.10 | | 1 | 2019-03-27 | | EDF | 171.25 | 2 | 2 | Jean | 2019-05-09 | 72.10 | | 2 | 2019-07-15 | | Peinture | 31.66 | 2 | 1 | Gwenn | 2019-07-21 | 10.55 | | 3 | 2019-07-20 | F1495 | Vitre | 18.25 | 1 | 2 | Jean | 2019-07-20 | 18.25 | +--------+------------+---------+----------+---------+--------+--------+--------+------------+---------+ 5 rows in set (0.00 sec)
heliconius
Messages postés
539
Date d'inscription
mardi 1 juillet 2008
Statut
Membre
Dernière intervention
23 juin 2023
139
22 juil. 2019 à 17:07
22 juil. 2019 à 17:07
Merci pour ta réponse.
OK. Mais je trouve beaucoup moins clair de répéter à chaque fois le nom de la table. Trop d'information tue l'information. Je ne mets, en principe le nom des tables que lorsqu'il y a ambiguïté. Mais si ça peut aider dans la compréhension de la requête, voici, avec tes préconisations et le plus clairement possible celle qui ne remplit pas l'objectif.
Tu proposes un second LEFT JOIN. Ok, mais comment l'écrirais-tu ?
OK. Mais je trouve beaucoup moins clair de répéter à chaque fois le nom de la table. Trop d'information tue l'information. Je ne mets, en principe le nom des tables que lorsqu'il y a ambiguïté. Mais si ça peut aider dans la compréhension de la requête, voici, avec tes préconisations et le plus clairement possible celle qui ne remplit pas l'objectif.
SELECT fct_Factures.idfact, fct_Factures.datfact, fct_Factures.numfact, fct_Factures.objet, fct_Factures.totfact, fct_Factures.idtype, fct_Personnes.idpers, fct_Personnes.prenom, fct_Payer.datpay, fct_Payer.montant FROM fct_Personnes LEFT JOIN fct_Payer ON fct_Personnes.idpers=fct_Payer.idpers, fct_Factures WHERE fct_Payer.idfact=fct_Facture.idfact ORDER BY fct_Payer.idfact, fct_Personnes.idpers;
Tu proposes un second LEFT JOIN. Ok, mais comment l'écrirais-tu ?
yg_be
Messages postés
23399
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
17 décembre 2024
Ambassadeur
1 556
Modifié le 22 juil. 2019 à 17:36
Modifié le 22 juil. 2019 à 17:36
ton modèle me semble bizarre. si c'est une facture individuelle, ne devrait-on pas pouvoir déterminer pour qui?
avec ce modèle, on pourrait faire une requête qui, pour les factures totalement payées, retournerait les paiements faits. pour les factures non totalement payées, la requête retournerait toutes les personnes, et leurs paiements éventuels.
dans ton exemple, ajoute une facture individuelle non payée.
avec ce modèle, on pourrait faire une requête qui, pour les factures totalement payées, retournerait les paiements faits. pour les factures non totalement payées, la requête retournerait toutes les personnes, et leurs paiements éventuels.
dans ton exemple, ajoute une facture individuelle non payée.
heliconius
Messages postés
539
Date d'inscription
mardi 1 juillet 2008
Statut
Membre
Dernière intervention
23 juin 2023
139
22 juil. 2019 à 18:08
22 juil. 2019 à 18:08
Le modèle n'est pas bizarre. J'essaye de ne pas bidouiller mais de respecter les règles de Merise. L'objet Merise Factures n'a pas à contenir qui va payer. L'éventuel champ "Payeur" dans une table Factures ne peut contenir qu'une valeur et une seule. S'il n'y avait à chaque fois qu'un seul payeur, ce serait bon. Mais si c'est une facture partagée, comment ferais-tu ? La table Factures mentionne si c'est une facture individuelle ou partagée. C'est tout. Si trois ou quatre ou cinq personnes participent au paiement de la facture, il y aura trois, quatre ou cinq occurrences de l'objet Personnes dans la table Payer (et ce, pour une même facture).
Modèle:
La relation (payer) est une relation n-aire (toutes les cardinalités maximales sont à n). Il y a donc création d'une table (payer) dont l'identifiant est obtenu par la concaténation des identifiants des objets qui participent à la relation (idfact+idpers) plus éventuellement les propriété portées. Ici :
identifiant de la relation: idpers,idfact
propriétés portées : date de paiement, montant payé
=>
La relation (avoir pour [type]) est une relation une-aire (au moins l'une des cmax est à 1). Il n'y a donc pas crétation de table mais migration : l'objet dont la cmax est à 1, reçoit en plus de ses propres champs, l'identifiant de l'autre table (ici: idtype) d'où la table Factures :
=>
Le idtype de la table fct_Types a migré dans la table fct_Factures.
Regarde bien la table Payer, elle est tout à fait cohérente. Telle personne a payé pour telle facture telle somme a telle date. S'il est l'unique payeur, le numéro de facture n'apparaîtra qu'une fois et le montant payé correspondra au total de la facture. Si c'est une facture partagée, il y aura plusieurs fois le même numéro de facture pour des personnes différentes et naturellement le montant de tous les paiements sera égal au total de la facture partagée.
Mais je me pose la question de savoir comment tu écris des LEFT JOIN en cascade. Tu peux me montrer, STP ?
Modèle:
[Personnes]-0,n---(payer)---0,n-[Factures]-1,1---(avoir pour)---0,n-[Types]
La relation (payer) est une relation n-aire (toutes les cardinalités maximales sont à n). Il y a donc création d'une table (payer) dont l'identifiant est obtenu par la concaténation des identifiants des objets qui participent à la relation (idfact+idpers) plus éventuellement les propriété portées. Ici :
identifiant de la relation: idpers,idfact
propriétés portées : date de paiement, montant payé
=>
fct_Payer(idfact,idpers, datpay,montant)
La relation (avoir pour [type]) est une relation une-aire (au moins l'une des cmax est à 1). Il n'y a donc pas crétation de table mais migration : l'objet dont la cmax est à 1, reçoit en plus de ses propres champs, l'identifiant de l'autre table (ici: idtype) d'où la table Factures :
=>
fct_Factures(idfact,datfact,numfact,objet,tofact, idtype)
Le idtype de la table fct_Types a migré dans la table fct_Factures.
Regarde bien la table Payer, elle est tout à fait cohérente. Telle personne a payé pour telle facture telle somme a telle date. S'il est l'unique payeur, le numéro de facture n'apparaîtra qu'une fois et le montant payé correspondra au total de la facture. Si c'est une facture partagée, il y aura plusieurs fois le même numéro de facture pour des personnes différentes et naturellement le montant de tous les paiements sera égal au total de la facture partagée.
Mais je me pose la question de savoir comment tu écris des LEFT JOIN en cascade. Tu peux me montrer, STP ?
22 juil. 2019 à 18:48
--- MERCI ---
T'es né comme ça ou c'est dû à 30 années de pratique ? :-)
Je ne vois vraiment pas quoi te dire à part un grand merci et te souhaiter de bonnes vacances si elles ne sont pas encore prises ou une bonne reprise si c'est déjà fait.
Je note la question comme résolue. Merci.
23 juil. 2019 à 08:37
Bon courage pour la suite