Você precisa de SQL dinâmico para isso, o que significa que você precisa criar uma função ou executar um
DO
comando. Como você não pode retornar valores diretamente do último, uma função plpgsql isto é:CREATE OR REPLACE function f_count_all(_tbl text
, OUT columns text[], OUT counts bigint[])
RETURNS record LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE (
SELECT 'SELECT
ARRAY[' || string_agg('''' || quote_ident(attname) || '''', ', ') || '],
ARRAY[' || string_agg('count(' || quote_ident(attname) || ')', ', ') || ']
FROM ' || _tbl
FROM pg_attribute
WHERE attrelid = _tbl::regclass
AND attnum >= 1 -- exclude tableoid & friends (neg. attnum)
AND attisdropped is FALSE -- exclude deleted columns
GROUP BY attrelid
)
INTO columns, counts;
END
$func$;
Ligar:
SELECT * FROM f_count_all('myschema.mytable');
Devoluções:
columns | counts
--------------+--------
{c1, c2, c3,} | {17 1,0}
Mais explicações e links sobre SQL dinâmico e
EXECUTE
nesta questão relacionada - ou mais algumas aqui no SO, tente esta pesquisa. Muito semelhante a esta pergunta:
postgresql - contagem (sem valores nulos) de cada coluna em uma tabela
Você pode até tentar retornar um tipo de registro polimórfico para obter colunas únicas dinamicamente, mas isso é bastante complexo e avançado. Provavelmente muito esforço para o seu caso. Mais nesta resposta relacionada.