简体   繁体   English

Postgresql枢轴?交叉?

[英]Postgresql pivot? Crosstab?

I have a table (which is the result of a query) in postgres that has a set of rows (the result of a complicated summation of data) that looks like the following: (The column names are the names of each day, and the value of each column is a double precision.) 我在postgres中有一个表(这是查询的结果),它有一组行(复杂的数据总和的结果),如下所示:(列名是每天的名称,以及每列的值是双精度。)

Sun Mon Tues Wed Thurs Fri 星期一星期二星期三星期四星期五
1.24 1.11 4.51 3.21 2.21 1.01 1.24 1.11 4.51 3.21 2.21 1.01

I need to have the data selected from one row so the results look like the below: 我需要从一行中选择数据,因此结果如下所示:

Day Amount 日金额
Sun 1.24 太阳1.24
Mon 1.11 星期一1.11
Tues 4.51 周二4.51
Wed 3.21 周三3.21
Thurs 2.21 周四2.21
Fri 1.01 周五1.01

I'm having difficulty just getting started, as I really need to change the column names to values and pivot the result. 我刚开始时遇到困难,因为我真的需要将列名更改为值并转动结果。 I tried experimenting with crosstab but I'm not entirely sure this is what I need. 我尝试过使用交叉表,但我并不完全确定这是我需要的。 Any advice or suggestions that could get me going in the right direction would be very much appreciated. 任何可以让我朝着正确的方向前进的建议或建议都将非常感激。

Modifying @Jack Douglas's first answer: 修改@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;

A little less costly according to the 9.0 query planner: 根据9.0查询规划器,成本稍低:

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

versus

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)

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);

alternative to @Unreason's answer without a union : 替换@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;

if you need to be more generic you could 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 bit neater in 8.4 with a using clause in the execute but I can't test that as I am on 8.3 你可以在8.4中using executeusing子句,但是我无法测试,因为我在8.3上

I don't know of direct implementation but maybe something like http://www.mail-archive.com/dhis2-users@lists.launchpad.net/msg00109.html could get you started 我不知道直接实现,但也许类似http://www.mail-archive.com/dhis2-users@lists.launchpad.net/msg00109.html可以让你入门

Of course if you don't need a flexible solution you can do 当然,如果您不需要灵活的解决方案,您可以这样做

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?) (星期六?)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM