Answers:
每个数据库安装一次附加模块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);
返回值:
栏目| 活跃 不活跃 --------- + -------- + ---------- A | 1 | 2 B | 4 | 5 C | 7 | -!!
C
:7
在第一列中填写了该值。有时,此行为是理想的,但对于此用例而言并非如此。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);
返回值:
栏目| 活跃 不活跃 --------- + -------- + ---------- 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)
结尾处有一个代码示例。
db <> 在这里拨弄
使用Tablefunc在多个列上进行透视 -还演示了提到的“额外的列”
\crosstabview
在psql中Postgres 9.6将此元命令添加到其默认的交互式终端psql中。您可以运行将用作第一个crosstab()
参数的查询,并将其输入\crosstabview
(立即或在下一步中)。喜欢:
db=> SELECT section, status, ct FROM tbl \crosstabview
与上面类似的结果,但是它是客户端专用的表示功能。输入行的处理略有不同,因此ORDER BY
不是必需的。\crosstabview
手册中的详细信息。该页面底部还有更多代码示例。
DanielVérité(psql功能的作者)对dba.SE的相关回答:
在以前接受的答案是过时的。
In practice the SQL query should always specify ORDER BY 1,2 to ensure that the input rows are properly ordered
您可以使用附加模块tablefunc的crosstab()
功能-您必须为每个数据库安装一次。从PostgreSQL 9.1开始,您可以使用:CREATE EXTENSION
CREATE EXTENSION tablefunc;
就您而言,我相信它看起来像这样:
CREATE TABLE t (Section CHAR(1), Status VARCHAR(10), Count integer);
INSERT INTO t VALUES ('A', 'Active', 1);
INSERT INTO t VALUES ('A', 'Inactive', 2);
INSERT INTO t VALUES ('B', 'Active', 4);
INSERT INTO t VALUES ('B', 'Inactive', 5);
SELECT row_name AS Section,
category_1::integer AS Active,
category_2::integer AS Inactive
FROM crosstab('select section::text, status, count::text from t',2)
AS ct (row_name text, category_1 text, category_2 text);
SELECT section,
SUM(CASE status WHEN 'Active' THEN count ELSE 0 END) AS active, --here you pivot each status value as a separate column explicitly
SUM(CASE status WHEN 'Inactive' THEN count ELSE 0 END) AS inactive --here you pivot each status value as a separate column explicitly
FROM t
GROUP BY section
sum()
,最好使用min()
or,max()
并且no也不ELSE
适合text
。但这与的效果略有不同corosstab()
,后者仅对每个属性使用“ first”值。只要只有一个就没关系。最后,性能也很重要。crosstab()
用C语言编写并针对任务进行了优化。
ERROR: 42803: aggregate function calls may not be nested
JSON聚合解决方案:
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', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7);
SELECT section,
(obj ->> 'Active')::int AS active,
(obj ->> 'Inactive')::int AS inactive
FROM (SELECT section, json_object_agg(status,ct) AS obj
FROM t
GROUP BY section
)X
抱歉,此操作尚不完整,因为我无法在此处进行测试,但这可能会使您朝正确的方向前进。我正在从我使用的翻译成类似查询的内容中进行翻译:
select mt.section, mt1.count as Active, mt2.count as Inactive
from mytable mt
left join (select section, count from mytable where status='Active')mt1
on mt.section = mt1.section
left join (select section, count from mytable where status='Inactive')mt2
on mt.section = mt2.section
group by mt.section,
mt1.count,
mt2.count
order by mt.section asc;
我正在使用的代码是:
select m.typeID, m1.highBid, m2.lowAsk, m1.highBid - m2.lowAsk as diff, 100*(m1.highBid - m2.lowAsk)/m2.lowAsk as diffPercent
from mktTrades m
left join (select typeID,MAX(price) as highBid from mktTrades where bid=1 group by typeID)m1
on m.typeID = m1.typeID
left join (select typeID,MIN(price) as lowAsk from mktTrades where bid=0 group by typeID)m2
on m1.typeID = m2.typeID
group by m.typeID,
m1.highBid,
m2.lowAsk
order by diffPercent desc;
它将返回一个typeID,最高出价和最低要求价以及两者之间的差额(正差额表示某物的价格可以低于其出售价格)。
Crosstab
该功能在tablefunc
扩展名下可用。您必须一次为数据库创建此扩展。
创建扩展tablefunc
;
您可以使用以下代码使用交叉表创建数据透视表:
create table test_Crosstab( section text,
<br/>status text,
<br/>count numeric)
<br/>insert into test_Crosstab values ( 'A','Active',1)
<br/>,( 'A','Inactive',2)
<br/>,( 'B','Active',4)
<br/>,( 'B','Inactive',5)
select * from crosstab(
<br/>'select section
<br/>,status
<br/>,count
<br/>from test_crosstab'
<br/>)as ctab ("Section" text,"Active" numeric,"Inactive" numeric)