Denne forespørgsel opretter den komplette DML-sætning, du leder efter:
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;
Du kan udføre den separat eller indpakke denne forespørgsel i en plpgsql-funktion og køre forespørgslen automatisk med EXECUTE
:
Fuld automatisering
Testet med 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;
Ring til:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Returnerer:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Forklar
Vanskeligheden er at definere RETURN
type for funktionen, mens antal og navne på kolonner, der returneres, vil variere. En detalje, der hjælper lidt:du vil kun have integer
kolonner.
Jeg løste dette ved at danne et array af bigint
(sum(int_col)
returnerer bigint
). Derudover returnerer jeg en række kolonnenavne. Begge sorteret alfabetisk efter kolonnenavn.
I funktionskaldet opdeler jeg disse arrays med unnest()
ankommer til det flotte format, der vises.
Den dynamisk oprettede og udførte forespørgsel er avancerede ting. Bliv ikke forvirret af flere lag af citater. Grundlæggende har du EXECUTE
der skal udføres af et tekstargument, der indeholder SQL-forespørgslen. Denne tekst leveres igen af sekundær SQL-forespørgsel, der bygger forespørgselsstrengen for den primære forespørgsel.
Hvis dette er for meget på én gang eller plpgsql
er ret nyt for dig, start med dette relaterede svar
hvor jeg forklarer det grundlæggende om en meget enklere funktion og giver links til manualen for de vigtigste funktioner.
Hvis ydelse er vigtigt at forespørge Postgres-kataloget direkte (pg_catalog.pg_attributes
) i stedet for at bruge de standardiserede (men langsomme) information_schema.columns
. Her er et simpelt eksempel med pg_attributes
.