Postgresql pivot? Cross?

I have a table (which is the result of a query) in postgres that has a rowset (the result of a complex summation of the data) that looks like this: (Column names are the names of every day, and the value of each column is double precision.)

Sun Mon Tue Wed & nbsp CHG; Fri
1.24 1.11 4.51 3.21 2.21 1.01

I need the data to be selected from one row, so the results are as follows:

Day amount
Sun 1.24
Mon 1.11
Tue 4.51
Wed 3.21
Thu 2.21
Fri 1.01

I'm having difficulty running, as I really need to change the column names to values ​​and rotate the result. I tried to experiment with a crosstab, but I'm not quite sure if this is what I need. Any advice or suggestions that could make me move in the right direction would be greatly appreciated.

+6
sql postgresql
source share
3 answers

Change @Jack Douglas first answer:

SELECT unnest(array['sun', 'mon', 'tue', 'wed', 'thu', 'fri']) AS day, unnest(array[sun, mon, tue, wed, thu, fri]) AS amount FROM t; 

A bit cheaper according to query planner 9.0:

Seq Scan on t (cost=0.00..11.62 rows=360 width=192)

against

Subquery Scan on z (cost=0.00..12.16 rows=360 width=68) -> Seq Scan on t (cost=0.00..11.26 rows=360 width=192)

+3
source share

test objects:

 create table t ( sun numeric, mon numeric, tue numeric, wed numeric, thu numeric, fri numeric ); insert into t(sun, mon, tue, wed, thu, fri) values(1.24, 1.11, 4.51, 3.21, 2.21, 1.01); 

@Unreason alternative answer without union :

 select day[i], amount[i] from ( select generate_series(1,6) as i, array['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'] as day, array[sun, mon, tue, wed, thu, fri] as amount from t ) z; 

If you need to be more general, you can do something like this:

 create or replace function unpivot(t) returns setof record language plpgsql immutable strict as $$ declare q record; r record; begin for q in ( select attname, attnum from pg_attribute where attnum>0 and attrelid = ( select oid from pg_class where relname = 't' ) ) loop for r in execute 'select '''||q.attname||'''::text, '|| '('||$1::text||'::t).'||q.attname||'::numeric' loop return next r; end loop; end loop; return; end;$$; select * from unpivot((select row(t.*)::t from t)) as foo(day text, amount numeric); 

you can be a little neat in 8.4 with the using clause in execute , but I can't verify this since I'm at 8.3

+1
source share

I don't know about direct implementation, but maybe something like http://www.mail-archive.com/ dhis2-users@lists.launchpad.net /msg00109.html can help you get started

Of course, if you do not need a flexible solution, you can make

 SELECT 'Sun' AS Day, Sun AS Value FROM TABLE WHERE ... UNION ALL SELECT 'Mon' AS Day, Mon AS Value FROM TABLE WHERE ... UNION ALL SELECT 'Tue' AS Day, Tue AS Value FROM TABLE WHERE ... UNION ALL SELECT 'Wed' AS Day, Wed AS Value FROM TABLE WHERE ... UNION ALL SELECT 'Thu' AS Day, Thu AS Value FROM TABLE WHERE ... UNION ALL SELECT 'Fri' AS Day, Fri AS Value FROM TABLE WHERE ... 

(Saturday?)

0
source share

All Articles