我在postgres中有一个表(这是一个查询的结果),它有一组行(复杂的数据总和的结果),如下所示:(列名是每天的名字,每列的值是双精度。)
太阳星期一星期三星期四星期四星期五 1.24 1.11 4.51 3.21 2.21 1.01我需要从一行中选择数据,因此结果如下所示:
日金额
太阳1.24
星期一1.11
周二4.51
周三3.21
周四2.21
周五1.01
我刚开始时遇到困难,因为我真的需要将列名更改为值并转动结果。我尝试过使用交叉表,但我并不完全确定这是我需要的。任何可以让我朝着正确的方向前进的建议或建议都会非常感激。
答案 0 :(得分:3)
修改@Jack Douglas的第一个答案:
SELECT unnest(array['sun', 'mon', 'tue', 'wed', 'thu', 'fri']) AS day,
unnest(array[sun, mon, tue, wed, thu, fri]) AS amount
FROM t;
根据9.0查询规划器,成本稍低:
Seq Scan on t (cost=0.00..11.62 rows=360 width=192)
与
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)
答案 1 :(得分:1)
测试对象:
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没有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;
如果你需要更通用,你可以做这样的事情:
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);
你可以在8.4中使用using
execute
中的{{1}}条款,但我无法测试,因为我在8.3
答案 2 :(得分:0)
我不知道直接实现,但是像http://www.mail-archive.com/dhis2-users@lists.launchpad.net/msg00109.html之类的东西可能会让你开始
当然,如果您不需要灵活的解决方案,您可以
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 ...
(星期六?)