Esta consulta crea la instrucción DML completa que busca:
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;
Puede ejecutarlo por separado o envolver esta consulta en una función plpgsql y ejecutar la consulta automáticamente con EXECUTE
:
Automatización completa
Probado con 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;
Llamar:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Devoluciones:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Explicar
La dificultad es definir el RETURN
type para la función, mientras que el número y los nombres de las columnas devueltas variarán. Un detalle que ayuda un poco:solo quieres integer
columnas.
Resolví esto formando una matriz de bigint
(sum(int_col)
devuelve bigint
). Además, devuelvo una matriz de nombres de columna. Ambos ordenados alfabéticamente por nombre de columna.
En la llamada de función, dividí estas matrices con unnest()
llegando al hermoso formato que se muestra.
La consulta creada y ejecutada dinámicamente es algo avanzado. No se confunda con múltiples capas de comillas. Básicamente tienes EXECUTE
que toma un argumento de texto que contiene la consulta SQL para ejecutar. Este texto, a su vez, lo proporciona la consulta SQL secundaria que crea la cadena de consulta de la consulta principal.
Si esto es demasiado a la vez o plpgsql
es bastante nuevo para usted, comience con esta respuesta relacionada
donde explico los conceptos básicos relacionados con una función mucho más simple y proporciono enlaces al manual para las funciones principales.
Si rendimiento es imprescindible consultar directamente el catálogo de Postgres (pg_catalog.pg_attributes
) en lugar de usar el information_schema.columns
estandarizado (pero lento) . Aquí hay un ejemplo simple con pg_attributes
.