ES
ERVIS SEFERI
Finance · Business · Technologie
← Retour · Je partage mes connaissances
IA & Automatisation · SQL et Python pour la finance

Le résultat qui ne part jamais seul

Le compte de résultat du semestre en une requête SQL : produits et charges dans la même lecture grâce à SUM(CASE), puis les trois réserves sans lesquelles -24 370,00 ne veut rien dire.

Dans le cadre de la rubrique « Je partage mes connaissances », je referme la série consacrée au grand livre du premier semestre 2026. Le premier article a fait apparaître un compte absent du plan comptable, le deuxième une dotation sans contrepartie et un loyer passé deux fois. Reste la question que pose toujours un dirigeant en fin de semestre : combien avons-nous gagné, ou perdu ? Je la traite ici en une seule requête SQL, avec les trois phrases sans lesquelles ce chiffre ne doit pas quitter votre bureau.

Lignes du grand livre passant par un SUM(CASE) qui les répartit en trois totaux : produits 295 450,00, charges 319 820,00, résultat -24 370,00 ; la banque et le compte 622600 sont écartés
Une seule lecture du grand livre : chaque ligne apporte son montant à la colonne qui la concerne, zéro aux autres.

La base est la même que dans les deux articles précédents : les tables ecritures et plan_comptes, chargées dans DB Browser for SQLite. Si vous partez de zéro, la mise en place est décrite dans le premier article.

Un seul passage sur le grand livre

Le réflexe Excel, c'est deux tableaux croisés dynamiques : l'un filtré sur la classe 7, l'autre sur la classe 6, et une soustraction dans une cellule à côté. Trois objets à tenir à jour, et une cellule que personne ne relira.

En SQL, la même chose tient en une requête, parce qu'une somme peut contenir une condition. Le motif s'écrit SUM(CASE WHEN … THEN … ELSE 0 END). Pour chaque ligne, le CASE décide ce qu'elle apporte au total : son montant si elle appartient à la catégorie, zéro sinon. Un SUM(CASE) par indicateur voulu, et toutes les colonnes sont calculées dans la même lecture.

Le cas

Sortir le compte de résultat simplifié du semestre sur une seule ligne : le total des produits (classe 7), le total des charges (classe 6) et le résultat.

La démarche

  1. Joindre ecritures à plan_comptes par un JOIN simple, cette fois. Le compte de résultat a besoin de la classe de chaque compte ; un compte sans classe n'a pas de place dans ce tableau. C'est la seule requête de la série où l'on veut que la jointure écarte une ligne, et c'est pour cela que le compte 622600 a été signalé avant, pas découvert après.
  2. Restreindre aux classes 6 et 7 avec WHERE p.classe IN (6, 7). WHERE est à sa place : la condition porte sur une ligne, pas sur une somme.
  3. Écrire les charges en debit - credit et les produits en credit - debit : les deux colonnes sortent positives et se lisent comme dans une liasse.
  4. Le résultat n'a besoin d'aucun CASE : credit - debit vaut déjà plus le produit pour la classe 7 et moins la charge pour la classe 6.
  5. Arrondir à deux décimales, puis F5.
SELECT ROUND(SUM(CASE WHEN p.classe = 7 THEN e.credit - e.debit ELSE 0 END), 2) AS produits,
       ROUND(SUM(CASE WHEN p.classe = 6 THEN e.debit - e.credit ELSE 0 END), 2) AS charges,
       ROUND(SUM(e.credit - e.debit), 2) AS resultat
FROM ecritures e
JOIN plan_comptes p ON e.compte = p.numero_compte
WHERE p.classe IN (6, 7);

Ce que vous devez obtenir

produitschargesresultat
295 450,00319 820,00-24 370,00

Une perte de 24 370,00 euros sur six mois. Le chiffre est exact : il est le reflet fidèle des 173 lignes du fichier. La suite dit pourquoi exact ne veut pas encore dire juste.

Le même motif, mois par mois

Celui qui lit -24 370,00 pose aussitôt la question suivante : une dérive régulière, ou un accident ? Le SUM(CASE) y répond avec une ligne de plus.

  1. Extraire le mois de la date avec substr(e.date_ecriture, 1, 7). Les dates sont stockées au format AAAA-MM-JJ : les sept premiers caractères donnent l'année et le mois.
  2. Ajouter cette expression au SELECT et au GROUP BY.
  3. Garder les trois SUM tels quels. Le motif ne change pas, seule la maille change.
SELECT substr(e.date_ecriture, 1, 7) AS mois,
       ROUND(SUM(CASE WHEN p.classe = 7 THEN e.credit - e.debit ELSE 0 END), 2) AS produits,
       ROUND(SUM(CASE WHEN p.classe = 6 THEN e.debit - e.credit ELSE 0 END), 2) AS charges,
       ROUND(SUM(e.credit - e.debit), 2) AS resultat
FROM ecritures e
JOIN plan_comptes p ON e.compte = p.numero_compte
WHERE p.classe IN (6, 7)
GROUP BY substr(e.date_ecriture, 1, 7)
ORDER BY mois;
moisproduitschargesresultat
2026-0145 820,0052 000,00-6 180,00
2026-0248 560,0051 050,00-2 490,00
2026-0347 960,0053 300,00-5 340,00
2026-0451 550,0057 240,00-5 690,00
2026-0548 040,0052 980,00-4 940,00
2026-0653 520,0053 250,00270,00

Cinq mois de perte, un seul mois positif : juin, à +270,00. Et deux mois qui portent plus que leur réalité. Avril est alourdi des 3 200,00 du loyer passé deux fois : sans lui, il tombe à -2 490,00, au niveau de février. Mai porte les 350,00 de la dotation sans contrepartie.

Additionnez les six lignes : vous retrouvez -24 370,00 au centime. Un découpage qui ne retombe pas sur le total est un découpage faux. Faites le contrôle à chaque fois, avant de commenter le moindre mois.

Les trois phrases qui accompagnent le chiffre

Annoncer -24 370,00 seul, c'est le seul vrai défaut possible de ce travail. Le chiffre contient deux anomalies et en exclut une troisième, toutes déjà localisées dans la série. Chacune peut déplacer le résultat d'un montant connu.

Cascade partant du résultat brut de -24 370,00 : +3 200,00 pour le doublon de loyer, -1 850,00 pour le compte 622600, 0 ou +350,00 pour la dotation sans contrepartie, soit -23 020,00 ou -22 670,00 après rectification
Les réserves ne remplacent pas le chiffre : elles l'encadrent, montant par montant.
RéserveOù elle se trouveEffet possible sur le résultat
Loyer d'avril passé deux fois (613000, 30-04)Dans les charges+3 200,00 si le doublon est confirmé
Dotation complémentaire de mai sans contrepartie (681000, 31-05)Dans les charges0,00 si seule la contrepartie manque au bilan ; +350,00 si la ligne elle-même est une erreur
Honoraires comptables de mars sur un compte hors plan (622600)Hors du résultat-1 850,00 si le compte est ouvert en classe 6

Si la comptabilité confirme le doublon et ouvre le compte 622600 en classe 6, le résultat rectifié est de -23 020,00. Il passe à -22 670,00 si la dotation de 350,00 se révèle elle-même une erreur. Écart maximal avec le chiffre brut : 1 700,00 euros, soit 7 % de la perte annoncée. Pas de quoi changer le sens du semestre ; largement de quoi faire douter d'un tableau de bord qui l'aurait affiché sans explication.

Ces montants n'ont pas à remplacer -24 370,00 dans l'outil. Un résultat rectifié n'existe que le jour où quelqu'un a rectifié le grand livre. D'ici là, la bonne communication tient en trois phrases, placées sous le chiffre :

  • le résultat inclut un loyer d'avril vraisemblablement passé deux fois, pour 3 200,00 ;
  • il inclut une dotation de 350,00 sans contrepartie au 31 mai ;
  • il exclut 1 850,00 d'honoraires comptables passés en mars sur un compte absent du plan.
Un chiffre n'est pas faux parce qu'il contient une anomalie connue. Il devient faux le jour où on le transmet sans elle.

Les erreurs qui coûtent une soirée

  • Oublier le WHERE. Sans la restriction aux classes 6 et 7, les deux CASE continuent de filtrer, mais la colonne du résultat additionne aussi les comptes de bilan : la requête renvoie 1 500,00. Un chiffre qui a l'allure d'un bénéfice et ne veut rien dire.
  • Classer par le numéro plutôt que par le plan. Un WHERE e.compte LIKE '6%' OR e.compte LIKE '7%', sans jointure, fait entrer le 622600 dans les charges sans que personne l'ait décidé : -26 220,00 au lieu de -24 370,00. Le plan comptable fait référence. Un compte qui n'y figure pas se signale ; il ne se reclasse pas en silence.
  • Oublier le ELSE 0. Sans lui, le CASE renvoie NULL pour les lignes hors catégorie. SUM ignore les NULL et le total reste juste, jusqu'au jour où aucune ligne ne correspond : la colonne affiche alors NULL au lieu de 0, et le premier calcul qui la reprend devient NULL à son tour.
  • Mélanger les sens. Une charge écrite en credit - debit sort négative. Le résultat reste juste, mais la colonne devient illisible pour qui lit une liasse. Convention de la liasse pour les colonnes, convention comptable pour le résultat.
  • Sommer après une jointure qui duplique. Ici, plan_comptes compte une ligne par compte : la jointure ne multiplie rien. Le jour où la table de droite porte plusieurs lignes par compte, un plan par exercice par exemple, chaque montant est compté autant de fois. Vérifiez la cardinalité avant de sommer, pas après avoir vu un total trop grand.

La série se referme ici : un contrôle de chargement, une balance, un compte hors plan, un déséquilibre, un doublon, un libellé vide, et un résultat qui part avec ses réserves. Aucune anomalie n'a été rectifiée dans l'outil. Toutes ont été montrées, chiffrées et adressées à qui de droit.

Pour reprendre la série depuis le début, avec le contrôle de chargement et la balance en LEFT JOIN : le compte que la jointure faisait disparaître.

Versions : article rédigé d'après DB Browser for SQLite 3.13.1, la version proposée au téléchargement sur sqlitebrowser.org (interface en français). Les requêtes sont du SQL standard et s'exécutent à l'identique dans PostgreSQL ou DuckDB ; les noms de menus peuvent changer d'une version de l'outil à l'autre.