mardi 18 mars 2014

Sous-totaux dans terminal psql

Nous allons dans un terminal psql (connecté à la base de données bdtest) produire un tableau avec sous-totaux par mois tel que celui construit dans ce billet.
L'instruction SQL se présentera suivant le schéma:

SELECT ligne détail
UNION
SELECT ligne sous-total
UNION
SELECT ligne total

étant entendu que chaque SELECT devra produire le même nombre de colonne avec le même type de données. Ainsi si la 4ième colonne de la ligne détail est une date, il faudra que cela soit aussi une date pour les deux SELECT suivant, ce qui évidemment posera un grave problème. C'est pourquoi nous afficherons dans la ligne détail les dates avec le type 'text'. Toutes les instructions nécessaire à la production du tableau seront placées dans un fichier bilan.sql que voici:


\set QUIET
\pset numericlocale on
\pset footer off
\pset linestyle u
\pset title 'Bilan'
\pset border 2
\o | awk 'NR==4 {y=$0};/SOUS-TOTAL/ {print y;print;print y};!/SOUS-TOTAL/'
SELECT mois_n ||'-' || mois AS "Mois",  '' AS " ", reference,
date_exec::text, crédit, débit,
  (SELECT SUM(solde)
  FROM opérationsv B
  WHERE B.reference <= A.reference
  AND B.an = A.an
  AND B.mois_n = A.mois_n) AS solde,
  contrepartie AS "usage"
FROM opérationsv A
WHERE an = '2013'
UNION
SELECT mois_n || '-' || mois, 'SOUS-TOTAL', '', '',
SUM(crédit) AS crédit, SUM(débit) AS débit, SUM(solde) AS solde,
'' AS " "
FROM opérationsv
WHERE an = '2013'
GROUP BY mois_n, mois
UNION
SELECT 'Ensemble', 'TOTAL', '', '',
SUM(crédit) AS crédit, SUM(débit) AS débit, SUM(solde) AS solde,
'' AS " "
FROM opérationsv
WHERE an = '2013'
ORDER by 1, 2 , 3;
\pset footer
\pset title
\pset border 1
\unset QUIET
\o

La deuxième colonne de la ligne détail est une colonne vide qui laissera la place au mot 'SOUS-TOTAL' et 'TOTAL' pour les deux SELECT suivant.
L'output est envoyé dans awk en vue de quelques améliorations.
Examinons de plus près les instructions awk:
  1. NR==4 {y=$0}
  2. /SOUS-TOTAL/ {print y;print;print y}
  3. !/SOUS-TOTAL/
Instruction 1: la ligne de séparation qui est la 4ième ligne lue est sauvegardée dans y
Instruction 2: toute ligne contenant le mot 'SOUS-TOTAL' est imprimée précédée et suivie de y (ligne de séparation)
Instruction 3: toutes les lignes sont imprimées (action par défaut) sauf les lignes avec 'SOUS-TOTAL' puisqu'elles l'ont déjà été.
Et voici le résultat:



Pour rappel la table opérations ainsi que la vue opérationsv sont définies dans cet article.
Depuis lors les données suivantes ont été ajoutées:

2013-0020 2013-03-28 -956.00 Loyer 
2013-0021 2013-03-31 1874.56 RN1
2013-0022 2013-03-31 -78.45 GS
2013-0023 2013-04-05 -119.23 cela
2013-0024 2013-04-12 -303.54 Tél
2013-0025 2013-04-15 -46.00 cela