每个数据库安装一次附加模块tablefunc
,它提供了功能。从 Postgres 9.1 开始,您可以使用:crosstab()
CREATE EXTENSION
CREATE EXTENSION IF NOT EXISTS tablefunc;
改进的测试用例
CREATE TABLE tbl (
section text
, status text
, ct integer -- "count" is a reserved word in standard SQL
);
INSERT INTO tbl VALUES
('A', 'Active', 1), ('A', 'Inactive', 2)
, ('B', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7); -- ('C', 'Active') is missing
简单的形式 - 不适合缺少的属性
crosstab(text)
有1 个输入参数:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- needs to be "ORDER BY 1,2" here
) AS ct ("Section" text, "Active" int, "Inactive" int);
回报:
部分 | 活跃 | 不活跃
---------+--------+----------
一个 | 1 | 2
乙| 4 | 5
C | 7 | ——!!
- 无需铸造和重命名。
- 注意 : 的错误结果是为第一列填写
C
的值。7
有时,这种行为是可取的,但不适用于此用例。
- 简单形式也仅限于提供的输入查询中的三列:row_name、category、value。没有像下面的 2 参数替代方案那样的额外列的空间。
安全形式
crosstab(text, text)
有2 个输入参数:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- could also just be "ORDER BY 1" here
, $$VALUES ('Active'::text), ('Inactive')$$
) AS ct ("Section" text, "Active" int, "Inactive" int);
回报:
部分 | 活跃 | 不活跃
---------+--------+----------
一个 | 1 | 2
乙| 4 | 5
C | | 7—— !!
手册上是这样的。
由于无论如何您都必须拼出列定义列表中的所有列(预定义的变体除外),因此在如下所示的表达式中提供简短列表通常更有效:crosstabN()
VALUES
$$VALUES ('Active'::text), ('Inactive')$$)
或者(不在手册中):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
我使用美元报价使报价更容易。
只要值列的文本表示是目标类型的有效输入,您甚至可以输出具有不同数据类型的列。crosstab(text, text)
这样,您可能具有不同的属性 kind 和 output text
,等date
,numeric
用于各自的属性。手册章节crosstab(text, text)
末尾有一个代码示例。
db<>在这里摆弄
多余输入行的影响
多余的输入行的处理方式不同 -(section, status)
在上面的示例中,相同(“row_name”,“category”)组合的重复行。
1参数表单从左到右填写可用值列。多余的值被丢弃。
较早的输入行获胜。
2 参数形式将每个输入值分配给其专用列,覆盖任何先前的分配。
稍后输入行获胜。
通常,您一开始就没有重复项。但如果您这样做,请根据您的要求仔细调整排序顺序 - 并记录发生的情况。
如果您不在乎,也可以快速获得任意结果。请注意效果。
高级示例
\crosstabview
在 psql 中
Postgres 9.6将此元命令添加到其默认交互式终端psql中。您可以运行将用作第一个crosstab()
参数的查询并将其提供给\crosstabview
(立即或在下一步中)。像:
db=> SELECT section, status, ct FROM tbl \crosstabview
与上面类似的结果,但它是客户端专有的表示功能。输入行的处理方式略有不同,因此ORDER BY
不需要。手册中的详细信息\crosstabview
。该页面底部有更多代码示例。
Daniel Vérité(psql 功能的作者)对 dba.SE 的相关回答: