Essa consulta cria a instrução DML completa que você procura:
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;
Você pode executá-lo separadamente ou envolver esta consulta em uma função plpgsql e executar a consulta automaticamente com
EXECUTE
:Automação total
Testado com 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;
Ligar:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Devoluções:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Explicar
A dificuldade é definir o
RETURN
type para a função, enquanto o número e os nomes das colunas retornadas variam. Um detalhe que ajuda um pouco:você só quer integer
colunas. Eu resolvi isso formando uma matriz de
bigint
(sum(int_col)
retorna bigint
). Além disso, retorno uma matriz de nomes de colunas. Ambos classificados em ordem alfabética pelo nome da coluna. Na chamada da função, divido esses arrays com
unnest()
chegando ao formato bonito exibido. A consulta criada e executada dinamicamente é algo avançado. Não se confunda com várias camadas de citações. Basicamente você tem
EXECUTE
que recebe um argumento de texto contendo a consulta SQL para execução. Esse texto, por sua vez, é fornecido pela consulta SQL secundária que constrói a string de consulta da consulta primária. Se isso for muito de uma vez ou
plpgsql
é bastante novo para você, comece com esta resposta relacionada
onde explico o básico sobre uma função muito mais simples e forneço links para o manual dos principais recursos. Se desempenho é essencial consultar directamente o catálogo Postgres (
pg_catalog.pg_attributes
) em vez de usar o padronizado (mas lento) information_schema.columns
. Aqui está um exemplo simples com pg_attributes
.