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

Transposition dynamique pour une valeur de ligne inconnue dans le nom de la colonne sur postgres

Vous ne pouvez pas avoir de pivot "dynamique" car le nombre, les noms et les types de données de toutes les colonnes d'une requête doivent être connus de la base de données avant la requête est réellement exécutée (c'est-à-dire au moment de l'analyse).

Je trouve qu'il est plus facile d'agréger des éléments dans un JSON.

select customer_number,
       jsonb_object_agg(label, value) as props
from the_table
group by customer_number

Si votre interface peut gérer directement les valeurs JSON, vous pouvez vous arrêter ici.

Si vous avez vraiment besoin d'une vue avec une colonne par attribut, vous pouvez les utiliser à partir de la valeur JSON :

select customer_number, 
       props ->> 'address' as address,
       props ->> 'phone' as phone,
       props ->> 'email' as email
from (       
  select customer_number,
         jsonb_object_agg(label, value) as props
  from the_table
  group by customer_number
) t

Je trouve cela un peu plus facile à gérer lorsque de nouveaux attributs sont ajoutés.

Si vous avez besoin d'une vue avec toutes les étiquettes, vous pouvez créer une procédure stockée pour la créer dynamiquement. Si le nombre d'étiquettes différentes ne change pas trop souvent, ceci peut être une solution :

create procedure create_customer_view() 
as
$$
declare
  l_sql text;
  l_columns text;
begin
  select string_agg(distinct format('(props ->> %L) as %I', label, label), ', ')
    into l_columns
  from the_table;
  
  l_sql := 
    'create view customer_properties as 
     select customer_number, '||l_columns||' 
     from (
      select customer_number, jsonb_object_agg(label, value) as props
       from the_table 
       group by customer_number 
     ) t';
  execute l_sql;
end;
$$
language plpgsql;

Créez ensuite la vue en utilisant :

call create_customer_view();  

Et dans votre code, utilisez simplement :

select *
from customer_properties;

Vous pouvez programmer cette procédure pour qu'elle s'exécute à intervalles réguliers (par exemple via un cron travail sous Linux)