Główny problem z tabelami przestawnymi w Postgresie (i innych RDBMS) polega na tym, że struktura (liczba i nazwy kolumn) wyniku zapytania nie może się różnić w zależności od wybranych danych. Jednym z możliwych rozwiązań jest dynamiczne tworzenie widoku, którego strukturę określają dane. Przykładowa funkcja tworzy widok na podstawie tabeli 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 $$;
Użyj funkcji po zmodyfikowaniu tabeli (być może w wyzwalaczu) i zapytaj o utworzony widok:
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)
Przetestuj go w db<>skrzypcach.
Zwróć uwagę, że konieczne jest odtworzenie widoku (wywołanie funkcji) dopiero po dodaniu nowej nazwy do tabeli (lub usunięciu z niej jakiejś nazwy). Jeśli zestaw odrębnych nazw się nie zmienia, możesz wysłać zapytanie do widoku bez jego ponownego tworzenia. Jeśli zestaw jest często modyfikowany, lepszym rozwiązaniem byłoby utworzenie tymczasowego widoku.
Możesz być także zainteresowany spłaszczeniem zagregowanych par klucz/wartość z pola JSONB?