SQL : avoir un décompte égal à zéro si pas de correspondance avec LEFT JOIN

Récemment pour un projet, j’ai eu à faire une série de diagramme voir image ci-dessous :

Deux périodes avec des données pas toujours consistentes, des barres de taille hétérogène, pas top pour l’affichage. On veut la taille des barres constantes, donc forcer l’affichage des données même si le décompte est zéro.

Le soucis c’est que chaque mois, on n’a pas forcément chaque libellé, donc les données qui sont fournit avec une requête inner join, ne retourne rien, et j’ai des fois deux barre au lieu de 5 voir plus.

Il fallait trouver un moyen de retourner tous les libellé, même si le décompte retournait 0.

Ainsi on aura des graphiques plus harmonieux, et pas des barres de différentes tailles suivant les périodes.

Le technique : elle consiste à retourner dans un premier temps dans une sous requêtes des données faites avec un INNER JOIN, donc dans ce cas, on aura seulement deux barres, mais dans un second temps on va prendre le résultat de cette sous-requête et faire une jointure à nouveau avec la table de tous les libellés existants, mais cette fois ci avec un LEFT JOIN, ainsi on aura tous les libellés. Il faut voir le résultat de la sous requête comme une nouvelle table, c’est la clé de cette technique.

Requête d’origine menant au graphique présenté

SELECT count(*) as count, MD.ID_ETAT_MATRICE_DETAILS, MD.LIBELLE_ETAT_MATRICE_DETAILS as libelle 
FROM MATRICE M
LEFT JOIN ETAT_MATRICE_DETAILS MD on MD.ID_ETAT_MATRICE_DETAILS = M.ID_ETAT_MATRICE_DETAILS
 where M.ID_ETAT_MATRICE = 3 and M.DATE_SIGNATURE BETWEEN '2020-07-01' AND '2020-07-30' 
 AND USR_ID = '9999'
 GROUP BY MD.ID_ETAT_MATRICE_DETAILS;

Nouvelle requête en transformant en sous requête la requête actuelle, et en faisant une jointure avec la table des libellés

SELECT IFNULL(count,0), C.ID_ETAT_MATRICE_DETAILS , EMD.LIBELLE_ETAT_MATRICE_DETAILS 
	FROM ETAT_MATRICE_DETAILS EMD
	LEFT JOIN 
(SELECT count(*) as count, MD.ID_ETAT_MATRICE_DETAILS , MD.LIBELLE_ETAT_MATRICE_DETAILS as libelle 
FROM MATRICE M
INNER JOIN ETAT_MATRICE_DETAILS MD on MD.ID_ETAT_MATRICE_DETAILS = M.ID_ETAT_MATRICE_DETAILS
 where M.ID_ETAT_MATRICE = 3 and M.DATE_SIGNATURE BETWEEN '2020-07-01' AND '2020-07-30' 
 AND USR_ID = '9999'
 GROUP BY MD.ID_ETAT_MATRICE_DETAILS)  
 C on C.ID_ETAT_MATRICE_DETAILS = EMD.ID_ETAT_MATRICE_DETAILS
 WHERE EMD.ID_ETAT_MATRICE = 3;

Notez que j’ai forcé à zéro le décompte si il vaut null (en effet LEFT JOIN retourne une donnée même s’il n’y a pas de correspondance, donc ça devient NULL.)

Retour en haut