Questa query crea l'istruzione DML completa che stai cercando:
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;
Puoi eseguirlo separatamente o racchiudere questa query in una funzione plpgsql ed eseguire automaticamente la query con EXECUTE
:
Automazione completa
Testato 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;
Chiama:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Resi:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Spiega
La difficoltà è definire il RETURN
digitare per la funzione, mentre il numero e i nomi delle colonne restituite varieranno. Un dettaglio che aiuta un po':vuoi solo integer
colonne.
Ho risolto questo problema formando un array di bigint
(sum(int_col)
restituisce bigint
). Inoltre, restituisco un array di nomi di colonne. Entrambi ordinati alfabeticamente in base al nome della colonna.
Nella chiamata di funzione ho diviso questi array con unnest()
arrivando al bel formato visualizzato.
La query creata ed eseguita dinamicamente è roba avanzata. Non lasciarti confondere da più livelli di virgolette. Fondamentalmente hai EXECUTE
che accetta un argomento di testo contenente la query SQL da eseguire. Questo testo, a sua volta, è fornito dalla query SQL secondaria che crea la stringa di query della query primaria.
Se è troppo in una volta o plpgsql
è piuttosto nuovo per te, inizia con questa risposta correlata
dove spiego le nozioni di base relative a una funzione molto più semplice e fornisco collegamenti al manuale per le caratteristiche principali.
Se prestazioni è essenziale interrogare direttamente il catalogo Postgres (pg_catalog.pg_attributes
) invece di usare lo standardizzato (ma lento) information_schema.columns
. Ecco un semplice esempio con pg_attributes
.