Bonjour à tous et à toutes,
J'aimerais vous soumettre une petite interrogation qui nous laisse passablement perplexe, mes collègues et moi, concernant la logique des jointures, et en particulier celle des RIGHT JOIN, dans un cas bien précis décrit ci-dessous.
Environnement: MySQL / PHP
Soit le modèle logique de données suivant:
Populé de la manière suivante:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
- ref_etat_contrat_rec (rec_id, rec_code, rec_libelle)
- rec_id INT auto_implement PRIMARY KEY
- rec_code VARCHAR(16) NOT NULL
- rec_libelle VARCHAR(50) NOT NULL
- contrat_con (con_id, #rec_id, con_date_debut, con_date_fin)
- con_id INT auto_implement PRIMARY KEY
- rec_id INT FOREIGN KEY references ref_etat_contrat_rec (rec_id)
- con_date_debut DATE NOT NULL
- con_date_fin DATE
- suivi_traitement_stt (stt_id, stt_date_debut, stt_date_fin)
- stt_id INT auto_implement PRIMARY KEY
- stt_date_debut DATETIME NOT NULL
- stt_date_fin DATETIME
- facture_fac(fac_id, #con_id, #stt_id, fac_date, fac_total_ht, fac_total_ttc)
- fac_id INT auto_implement PRIMARY KEY
- con_id INT FOREIGN KEY references contrat_con (con_id)
- stt_id INT FOREIGN KEY references suivi_traitement_stt (stt_id)
- fac_total_ht DECIMAL(16,4)
- fac_total_ttc DECIMAL(16,4)
ref_etat_contrat_rec
contrat_con
rec_id rec_code rec_libelle 1 cree Crée 2 actif Actif 3 resil_en_cours En cours de résiliation 4 resilie Résilié 5 suppr Supprimé
suivi_traitement_stt
con_id rec_id con_date_debut con_date_fin 24 2 2017-05-17 NULL 32 2 2017-09-01 NULL
facture_fac
stt_id stt_date_debut stt_date_fin 76 2017-10-13 13:35:14 2017-10-13 13:37:28
fac_id con_id stt_id fac_date fac_total_ht fac_total_ttc 4 32 76 2017-09-01 47.40 50.0070 5 32 76 2017-09-01 474.00 500.07
En débogage pour vérifier des statistiques générées, je cherche à vérifier le nombre de contrats actifs ou non statués ayant fait l'objet d'une facture. Pour se faire, j'ai à disposition la requête ci-dessous
En soit, la logique de la requête me semble fausse (la correction transforme le RIGHT JOIN en LEFT JOIN).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 SELECT 'Nombre de contrats actifs facturés' AS libelle, COUNT(con.con_id) AS NB FROM contrat_con AS con INNER JOIN (SELECT DISTINCT fac.con_id FROM facture_fac AS fac WHERE fac.stt_id = 76 ) AS SRFac ON con.con_id = SRFac.con_id RIGHT JOIN ref_etat_contrat_rec AS rec ON con.rec_id = rec.rec_id WHERE con.rec_id = 2 OR con.rec_id IS NULL
Pour autant, le résultat attendu de cette requête devrait être 1.
Hors, cette requête renvoie la valeur 0.
Si l'on enlève la clause OR con.rec_id IS NULL, on retrouve le bon résultat.
Même chose si l'on enlève la jointure interne.
Cependant, la requête nécessite bien les deux clauses, les enlever n'est donc pas envisageable.
J'ai appliqué le correctif énoncé, donc le problème ne se pose plus, mais la logique du résultat m'échappe, et j'aimerais bien comprendre.
Est-ce que quelqu'un saurait m'expliquer ce qu'il se passe dans cette requête pour que le résultat soit 0 et non pas 1 ?
En vous remerciant par avance,
Cordialement,
Thomas
Partager