Cette requête crée l'instruction DML complète que vous recherchez :
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;
Vous pouvez l'exécuter séparément ou envelopper cette requête dans une fonction plpgsql et exécuter la requête automatiquement avec EXECUTE
:
Automatisation complète
Testé avec 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;
Appel :
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Renvoie :
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Expliquez
La difficulté est de définir le RETURN
type pour la fonction, tandis que le nombre et les noms des colonnes renvoyées varient. Un détail qui aide un peu :vous ne voulez que integer
colonnes.
J'ai résolu ce problème en formant un tableau de bigint
(sum(int_col)
renvoie bigint
). De plus, je renvoie un tableau de noms de colonnes. Les deux sont triés par ordre alphabétique par nom de colonne.
Dans l'appel de fonction, j'ai divisé ces tableaux avec unnest()
arriver au beau format affiché.
La requête créée et exécutée dynamiquement est un élément avancé. Ne vous laissez pas confondre par plusieurs couches de citations. En gros, vous avez EXECUTE
qui prend un argument texte contenant la requête SQL à exécuter. Ce texte, à son tour, est fourni par une requête SQL secondaire qui construit la chaîne de requête de la requête principale.
Si c'est trop à la fois ou plpgsql
est plutôt nouveau pour vous, commencez par cette réponse connexe
où j'explique les bases d'une fonction beaucoup plus simple et fournit des liens vers le manuel pour les principales fonctionnalités.
Si les performances est indispensable interroger directement le catalogue Postgres (pg_catalog.pg_attributes
) au lieu d'utiliser le standardisé (mais lent) information_schema.columns
. Voici un exemple simple avec pg_attributes
.