2015-10-20 39 views
2

我试图实现从我的数据如下:Postgres的交叉混乱

docid, yyyy, tiOne, tiTwo, tiThree, tiFour 
d1  2011 txtA txtB txtC 
d2  2012 txtD txtE txtF  txtG 
d3  2013 txtH txtI txtJ 
d4  2013 txtK 

这是如何重新创建我的数据:

CREATE TEMP TABLE t (
    docid text 
, yyyy int 
, timark text 
, txtmark text 
); 

INSERT INTO t VALUES 
    ('d1', 2011, 'tiOne', 'txtA'), 
    ('d1', 2011, 'tiTwo', 'txtB'), 
    ('d1', 2011, 'tiThree', 'txtC'), 
    ('d2', 2012, 'tiOne', 'txtD'), 
    ('d2', 2012, 'tiTwo', 'txtE'), 
    ('d2', 2012, 'tiThree', 'txtF'), 
    ('d2', 2012, 'tiFour', 'txtG'), 
    ('d3', 2013, 'tiOne', 'txtH'), 
    ('d3', 2013, 'tiTwo', 'txtI'), 
    ('d3', 2013, 'tiThree', 'txtJ'), 
    ('d4', 2013, 'tiOne', 'txtK') 
; 

这是我的代码

select * 
FROM crosstab(
     'SELECT docid, timark, txtmark 
     FROM t 
     ORDER BY 1,2') -- needs to be "ORDER BY 1,2" here 
AS ct ("docid" text, "timark" text, "txtmark" text); 

但我得到一个完全混淆输出如下:

docid timark txtmark 
d1 txtA txtC 
d2 txtG txtD 
d3 txtH txtJ 
d4 txtK 

的“tiOne”数据不是良好的结构,所以很难准确地知道什么是要在这些列,所以它不会容易硬编码这些值到代码

回答

1

交叉表查询别名应包含结果集的列名和类型。 源查询的结果应该按两列进行排序:行标识符(docid)和类别标识符(timark)。 不幸的是,类别名称的字母顺序不是预期的顺序。

在这种情况下,请使用具有两个参数的crosstab函数的形式。 第二个参数是按预期顺序选择所有类别的查询。 此形式的crosstab还允许有附加列(yyyy)并正确显示不完整的数据。

select * 
FROM crosstab(
    $$ SELECT docid, yyyy, timark, txtmark 
    FROM t 
    ORDER BY 1 $$, 
    $$ values ('tiOne'), ('tiTwo'), ('tiThree'), ('tiFour') $$) 
AS ct ("docid" text, "yyyy" text, "tiOne" text, "tiTwo" text, "tiThree" text, "tiFour" text); 

docid | yyyy | tiOne | tiTwo | tiThree | tiFour 
-------+------+-------+-------+---------+-------- 
d1 | 2011 | txtA | txtB | txtC | 
d2 | 2012 | txtD | txtE | txtF | txtG 
d3 | 2013 | txtH | txtI | txtJ | 
d4 | 2013 | txtK |  |   | 
(4 rows)  
+0

完美的工作。谢谢。 – woodbine