PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Dynamische Transponierung für unbekannten Zeilenwert in Spaltennamen auf Postgres

Sie können keinen "dynamischen" Pivot haben, da die Anzahl, Namen und Datentypen aller Spalten einer Abfrage der Datenbank vorher bekannt sein müssen die Abfrage wird tatsächlich ausgeführt (d. h. zur Parsing-Zeit).

Ich finde es einfacher, Dinge in einem JSON zu aggregieren.

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

Wenn Ihr Frontend direkt mit JSON-Werten umgehen kann, können Sie hier aufhören.

Wenn Sie wirklich eine Ansicht mit einer Spalte pro Attribut benötigen, können Sie diese aus dem JSON-Wert:

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

Ich finde das etwas einfacher zu handhaben, wenn neue Attribute hinzugefügt werden.

Wenn Sie eine Ansicht mit allen Bezeichnungen benötigen, können Sie eine gespeicherte Prozedur erstellen, um sie dynamisch zu erstellen. Wenn sich die Anzahl der verschiedenen Labels nicht allzu oft ändert, könnte dies eine Lösung sein:

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;

Erstellen Sie dann die Ansicht mit:

call create_customer_view();  

Und in Ihrem Code verwenden Sie einfach:

select *
from customer_properties;

Sie können diese Prozedur so planen, dass sie in regelmäßigen Abständen ausgeführt wird (z. B. durch einen cron Job unter Linux)