有谁知道如何在PostgreSQL中创建交叉表查询吗? 例如,我有下表:
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 ,该模块提供的功能。从Postgres 9.1开始,您可以使用:crosstab()CREATE EXTENSION
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个输入参数:
crosstab(text)
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);
返回值:
Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | 7 | -- !!
无需强制转换和重命名。 请注意以下错误结果C:7在第一列中填写了该值。有时,此行为是理想的,但对于此用例而言并非如此。 在简单的形式也被限制到恰好在所提供的输入查询三列:ROW_NAME,类别,值。像下面的2参数替代中一样,没有多余的空间容纳额外的列。
Safe form
crosstab(text, text)具有2个输入参数:
crosstab(text, text)
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);
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[])$$ -- short syntax for long lists
我使用美元报价来简化报价。
您甚至可以使用-输出具有不同数据类型的列,crosstab(text, text)只要值列的文本表示形式是目标类型的有效输入即可。这样,你可能有不同的属性种类和产量text,date,numeric等,为各自的属性。本手册本章crosstab(text, text)结尾处有一个代码示例。
\crosstabview 在psql中 Postgres 9.6将此元命令添加到其默认的交互式终端psql中。您可以运行将用作第一个crosstab()参数的查询,并将其输入\crosstabview(立即或在下一步中)。喜欢:
crosstab()
\crosstabview
db=> SELECT section, status, ct FROM tbl \crosstabview 与上面类似的结果,但是它是客户端专用的表示功能。输入行的处理略有不同,因此ORDER BY不是必需的。\crosstabview手册中的详细信息。该页面底部还有更多代码示例。
在以前接受的答案是过时的。
该功能的变型crosstab(text, integer)已过时。第二个integer参数将被忽略。我引用了当前的手册:
crosstab(text sql, int N) … 过时版本crosstab(text)。N现在将忽略该参数,因为值列的数量始终由调用查询确定
不必要的转换和重命名。
如果某行没有所有属性,它将失败。请参阅上面具有两个输入参数的安全变量,以正确处理缺少的属性。
ORDER BY是的一参数形式crosstab()。手册:
ORDER BY
在实践中,SQL查询应始终指定ORDER BY 1,2以确保输入行正确排序