To zapytanie tworzy pełną instrukcję DML, której szukasz:
WITH x AS (
SELECT 'public'::text AS _schema -- provide schema name ..
,'somereport'::text AS _tbl -- .. and table name once
)
SELECT 'SELECT ' || string_agg('sum(' || quote_ident(column_name)
|| ') AS sum_' || quote_ident(column_name), ', ')
|| E'\nFROM ' || quote_ident(x._schema) || '.' || quote_ident(x._tbl)
FROM x, information_schema.columns
WHERE table_schema = _schema
AND table_name = _tbl
AND data_type = 'integer'
GROUP BY x._schema, x._tbl;
Możesz wykonać je osobno lub zapakować to zapytanie w funkcję plpgsql i uruchomić zapytanie automatycznie za pomocą EXECUTE
:
Pełna automatyzacja
Testowane z PostgreSQL 9.1.4
CREATE OR REPLACE FUNCTION f_get_sums(_schema text, _tbl text)
RETURNS TABLE(names text[], sums bigint[]) AS
$BODY$
BEGIN
RETURN QUERY EXECUTE (
SELECT 'SELECT ''{'
|| string_agg(quote_ident(c.column_name), ', ' ORDER BY c.column_name)
|| '}''::text[],
ARRAY['
|| string_agg('sum(' || quote_ident(c.column_name) || ')'
, ', ' ORDER BY c.column_name)
|| ']
FROM '
|| quote_ident(_schema) || '.' || quote_ident(_tbl)
FROM information_schema.columns c
WHERE table_schema = _schema
AND table_name = _tbl
AND data_type = 'integer'
);
END;
$BODY$
LANGUAGE plpgsql;
Zadzwoń:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Zwroty:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Wyjaśnij
Trudność polega na zdefiniowaniu RETURN
typ dla funkcji, natomiast liczba i nazwy zwracanych kolumn będą się różnić. Jeden szczegół, który trochę pomaga:potrzebujesz tylko integer
kolumny.
Rozwiązałem to, tworząc tablicę bigint
(sum(int_col)
zwraca bigint
). Dodatkowo zwracam tablicę nazw kolumn. Oba posortowane alfabetycznie według nazwy kolumny.
W wywołaniu funkcji podzieliłem te tablice za pomocą unnest()
przybywając do pięknego wyświetlanego formatu.
Dynamicznie tworzone i wykonywane zapytanie to zaawansowana sprawa. Nie daj się zwieść wielu warstwom cytatów. Zasadniczo masz EXECUTE
który pobiera argument tekstowy zawierający zapytanie SQL do wykonania. Ten tekst z kolei jest dostarczany przez drugorzędne zapytanie SQL, które tworzy ciąg zapytania podstawowego.
Jeśli to za dużo na raz lub plpgsql
jest dla Ciebie raczej nowy, zacznij od tej powiązanej odpowiedzi
gdzie wyjaśnię podstawy dotyczące znacznie prostszej funkcji i podam linki do instrukcji dotyczących głównych funkcji.
Jeśli wydajność jest niezbędne, aby bezpośrednio przeszukiwać katalog Postgres (pg_catalog.pg_attributes
) zamiast używać standardowych (ale powolnych) information_schema.columns
. Oto prosty przykład z pg_attributes
.