4

I have 30 numeric numeric columns in a table .I want to find mean,std, percentiles for all the columns in table.I don't want to write all the column names manually like below

select date,
      avg(col1), stddev(col1),
      avg(col2), stddev(col2), 
from table name group by date;

Is there any way to find mean, std, percentiles for all the columns at once.

Kaushik Nayak
  • 29,706
  • 5
  • 28
  • 41
user8545255
  • 717
  • 3
  • 7
  • 15

2 Answers2

6

You can simplify the logic using a lateral join:

select which, min(val), max(val), stddev(val), avg(val)
from t, lateral
     (values ('col1', col1), ('col2', col2), . . . 
     ) v(which, val)
group by which;

You still have to list the columns, but you only need to do so once in the values clause.

Gordon Linoff
  • 1,198,228
  • 53
  • 572
  • 709
1

Dynamic SQL is a little bit trick in Greenplum.

Here is an example based on the instruction from https://www.pivotalguru.com/?p=266

$ psql postgres -c "create table foo (date date, c1 int, c2 int, c3 int);"
$ cat <<EOT >> /tmp/bar.sql
> select 'select ';
> select ' avg('  || attname || '), stddev(' || attname || '),' from pg_attribute
> where attrelid = 'foo'::regclass::oid and attnum > 0 and attname != 'date';
> select ' date from foo group by date;';
> EOT
$ psql -A -t  -f /tmp/foo.sql postgres | psql -a postgres
select 
 avg(c1), stddev(c1),
 avg(c2), stddev(c2),
 avg(c3), stddev(c3),
 date from foo group by date;
 avg | stddev | avg | stddev | avg | stddev | date 
-----+--------+-----+--------+-----+--------+------
Xin Zhang
  • 151
  • 1
  • 1
  • 9