例如我有下面的表:
Section Status Count A Active 1 A Inactive 2 B Active 4 B Inactive 5
我想查询返回以下交叉表:
Section Active Inactive A 1 2 B 4 5
这可能吗?
tablefunc
,它提供函数crosstab()。从Postgresql 9.1你可以使用
CREATE EXTENSION
:
CREATE EXTENSION tablefunc;
改进的测试用例
CREATE TEMP TABLE t ( section text,status text,ct integer -- don't use "count" as column name. ); INSERT INTO t VALUES ('A','Active',1),('A','Inactive',2),('B',4),5),('C',7); -- no row for C with 'Active'
> count是一个reserved word,不要使用它作为列名。
简单形式 – 不适合缺少属性
带有1个参数的交叉表(文本):
SELECT * FROM crosstab( 'SELECT section,status,ct FROM t ORDER BY 1,2') -- needs to be "ORDER BY 1,2" here AS ct ("Section" text,"Active" int,"Inactive" int);
返回:
Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | 7 |
>无需转换和重命名。
>注意C的错误结果:第一列填入值7。有时,这种行为是可取的,但不适用于此用例。
>简单形式也仅限于提供的输入查询中的三列:row_name,category,value。没有额外的列的空间,如在下面的2参数替代。
安全形式
交叉表(文本,文本)带有2个参数:
SELECT * FROM crosstab( 'SELECT section,ct FROM t ORDER BY 1,2' -- could also just be "ORDER BY 1" here,$$VALUES ('Active'::text),('Inactive')$$) AS ct ("Section" text,"Inactive" int);
返回:
Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | | 7
>注意C的正确结果。
>第二个参数可以是每个属性返回一行的任何查询,其匹配结束处的列定义的顺序。通常,您将需要从基础表中查询不同的属性,如下所示:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
这是在手册。
因为你必须拼写列定义列表中的所有列(除了预定义的crosstabN()变体),在VALUES表达式中提供一个短列表通常更有效率,如我演示:
$$VALUES ('Active'::text),('Inactive')$$)
要么:
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- shorter for long lists
这不是在手册。
>我使用dollar quoting使报价更容易。
高级示例
> Pivot on Multiple Columns using Tablefunc – 也演示了提到的“额外列”。
> Dynamic alternative to pivot with CASE and GROUP BY
纠正
previously accepted answer by Jeremiah已过时。
>函数crosstab(text,integer)的变体已过时。第二个整数参数被忽略。我引用current manual:
crosstab(text sql,int N)
…Obsolete version of
crosstab(text)
. The parameterN
is now ignored,
since the number of value columns is always determined by the calling query
>无需铸造和重命名。
>如果行没有所有属性,它将失败。有一个安全的变体,有两个文本参数正确处理缺少的属性。
> ORDER BY是必需的。我引用手册here:
In practice the sql query should always specify
ORDER BY 1,2
to ensure
that the input rows are properly ordered
(仅适用于在那里使用的一参数形式的crosstab())。