Footcow Blog - Mot-clé - extensionLinux, Base de données Postgresql, développement, Internet, emailing et déliverabilité.2024-03-29T12:29:38+01:00Hervé Piedvache alias Bill Footcow pour les intimesurn:md5:ef5d07bad25e414feca607a3b7f2af11DotclearPostgreSQL : Affichez vos données en ligne avec Crosstaburn:md5:015744d5d607947284c12404136b1a832011-09-11T23:18:00+02:002023-05-17T17:28:01+02:00Hervé PiedvachePostgreSQLcrosstabextensionpostgresql<p><img src="https://www.footcow.com/public/crosstab.png" alt="" style="display:table; margin:0 auto;" height="244" width="244" /></p>
<p>Quel client ne vous a pas demandé un jour de lui présenter des statistiques mensuelles de ses données ? Souvent il fallait faire les calculs, obtenir des agrégations et coder une interface de présentation qui prenait des résultats en colonne pour les remettre en ligne. Laborieux, souvent source d'erreur et de perte de temps cette méthode n'avait pas tellement d'équivalent directement en base de données.
La solution est apparue depuis quelques release de PostgreSQL, il suffit de savoir manipuler l'extension <a href="https://www.postgresql.org/docs/current/static/tablefunc.html" hreflang="en" title="Crosstab">Crosstab</a>.</p> <p>Prenons un exemple simple. Vous avez un table de données qui contient des contrats, et pour chacun d'eux vous avez des volumes d'affaires répartis par date de transaction. Comme par exemple :</p>
<pre>
contract_code | revenue | transaction_date
--------------+---------+-----------------
123456 | 123.00 | 2011-04-01
123456 | 456.00 | 2011-05-25
etc.
</pre>
<p>Normalement, pour faire votre statistique vous procédiez de la façon suivante :</p>
<pre>
SELECT contract_code AS row_name,
SUM(revenue) OVER (PARTITION BY contract_code) AS total,
TO_CHAR('2010-12-01'::date + (EXTRACT(month FROM transaction_date) || ' month')::interval, 'mon') AS cat
FROM contract
ORDER BY contract_code;
</pre>
<p>Ce qui donne le résultat suivant :</p>
<pre>
row_name | total | cat
---------+-----------+-----
123456 | 74.00 | jan
123456 | 123.00 | jan
123456 | 147.00 | feb
123456 | 587.00 | feb
123456 | 100.00 | mar
123456 | 57.00 | mar
etc.
</pre>
<p>C'est donc maintenant que l'extension <a href="https://www.postgresql.org/docs/current/static/tablefunc.html" hreflang="en" title="Crosstab">Crosstab</a> de PostgreSQL va entrer en jeu.</p>
<p>Pour cela il faut au préalable se préparer les colonnes d'affichage nécessaire pour la mise en ligne des données, par exemple dans notre cas en générant la liste des mois de l'année :</p>
<pre>
SELECT to_char('2010-12-01'::date + (n || ' month')::interval, 'mon') As short_mname
FROM generate_series(1,12);
</pre>
<p>Qui donne simplement le résultat suivant :</p>
<pre>
short_mname
-------------
jan
feb
mar
apr
may
jun
jul
aug
sep
oct
nov
dec
</pre>
<p>Puis monter votre requête en appelant l'extension Crosstab qui va faire la fonction de pivot entre vos données brutes de travail et votre table des mois afin de les afficher horizontalement :</p>
<pre>
SELECT *
FROM crosstab ('
SELECT contract_code AS row_name,
SUM(revenue) OVER (PARTITION BY contract_code) AS total,
TO_CHAR('2010-12-01'::date + (EXTRACT(month FROM transaction_date) || ' month')::interval, 'mon') AS cat
ORDER BY contract_code',
'SELECT
to_char(''2010-12-01''::date + (n || '' month'')::interval, ''mon'') As short_mname
FROM generate_series(1,12) n') as (code text, total numeric, jan numeric, feb numeric, mar numeric,
apr numeric, may numeric, jun numeric, jul numeric, aug numeric,
sep numeric, oct numeric, nov numeric, dec numeric)
ORDER BY total DESC
LIMIT 1;
</pre>
<p>Vous obtenez donc directement le résultat suivant :</p>
<pre>
code | total | jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec
--------+-----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
123456 | 2041.00 | 197 | 734 | 157 | 354 | 247 | 172 | | | | | |
</pre>
<p>Il ne vous reste plus qu'à prendre les données pour les afficher simplement dans votre tableau statistique, et le tour est joué !<br />
Un bon gain de temps pour tout le monde !</p>https://www.footcow.com/index.php/post/2011/09/12/PostgreSQL-%3A-Affichez-vos-donn%C3%A9es-en-ligne-avec-Crosstab#comment-formhttps://feeds.feedburner.com/FootcowBlog/comments/103