Le principal problème avec les tableaux croisés dynamiques dans Postgres (et autres SGBDR) est que la structure (nombre et noms de colonnes) d'un résultat de requête ne peut pas varier en fonction des données sélectionnées. Une des solutions possibles est de créer dynamiquement une vue dont la structure est définie par les données. La fonction example crée une vue basée sur la table example_table
:
create or replace function create_pivot_view()
returns void language plpgsql as $$
declare
list text;
begin
select string_agg(format('jdata->>%1$L "%1$s"', name), ', ')
from (
select distinct name
from example_table
) sub
into list;
execute format($f$
drop view if exists example_pivot_view;
create view example_pivot_view as
select lbl, %s
from (
select lbl, json_object_agg(name, value) jdata
from example_table
group by 1
order by 1
) sub
$f$, list);
end $$;
Utilisez la fonction après la modification de la table (peut-être dans un déclencheur) et interrogez la vue créée :
select create_pivot_view();
select *
from example_pivot_view;
lbl | num | colour | percentage
-----+-----+--------+------------
1 | 1 | Red | 25.0
2 | 2 | Green | 50.0
3 | 3 | Blue | 75.0
(3 rows)
Testez-le dans db<>fiddle.
Notez qu'il est nécessaire de recréer une vue (appelez la fonction) uniquement après qu'un nouveau nom a été ajouté à la table (ou qu'un nom en a été supprimé). Si l'ensemble de noms distincts ne change pas, vous pouvez interroger la vue sans la recréer. Si l'ensemble est modifié fréquemment, la création d'une vue temporaire serait une meilleure option.
Vous pourriez également être intéressé par Aplatir les paires clé/valeur agrégées à partir d'un champ JSONB ?