PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Transformer arbitrairement de nombreuses lignes en colonnes dans PostgreSQL

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 ?