Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL交叉表查询_Sql_Postgresql_Pivot_Case_Crosstab - Fatal编程技术网

PostgreSQL交叉表查询

PostgreSQL交叉表查询,sql,postgresql,pivot,case,crosstab,Sql,Postgresql,Pivot,Case,Crosstab,有人知道如何在PostgreSQL中创建交叉表查询吗? 例如,我有下表: 区段状态计数 主动1 A不活跃的2 B活动4 B非活动5 我希望查询返回以下交叉表: 部分活动-非活动 A 12 B 4 5 这可能吗?很抱歉,这还不完整,因为我无法在这里进行测试,但它可能会让您朝着正确的方向前进。我在翻译一个类似的查询: select mt.section, mt1.count as Active, mt2.count as Inactive from mytable mt left join (sel

有人知道如何在PostgreSQL中创建交叉表查询吗? 例如,我有下表:

区段状态计数 主动1 A不活跃的2 B活动4 B非活动5 我希望查询返回以下交叉表:

部分活动-非活动 A 12 B 4 5
这可能吗?

很抱歉,这还不完整,因为我无法在这里进行测试,但它可能会让您朝着正确的方向前进。我在翻译一个类似的查询:

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、最高出价和最低要求价格,两者之间的差异为正的差异意味着可以以低于销售价格的价格购买某些东西。

您可以使用的交叉表功能-必须为每个数据库安装一次。从PostgreSQL 9.1开始,您可以使用:

CREATE EXTENSION tablefunc;
CREATE EXTENSION IF NOT EXISTS 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 DISTINCT attribute FROM tbl ORDER BY 1'
每个数据库安装一次,它提供了交叉表功能。从Postgres 9.1开始,您可以使用:

CREATE EXTENSION tablefunc;
CREATE EXTENSION IF NOT EXISTS tablefunc;
改进的测试用例 简单表单-不适合缺少的属性 带有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);
返回:

Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | 7 | -- !! Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | | 7 -- !! 返回:

Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | 7 | -- !! Section | Active | Inactive ---------+--------+---------- A | 1 | 2 B | 4 | 5 C | | 7 -- !! 手册上有

由于您必须在列定义列表中拼出除预定义的crosstabN变体之外的所有列,因此在值表达式中提供一个短列表通常更有效,如所示:

$$VALUES ('Active'::text), ('Inactive')$$)
或不在手册中:

$$SELECT unnest('{Active,Inactive}'::text[])$$  -- short syntax for long lists
我过去常常使报价更容易

您甚至可以使用crosstabtext、text输出具有不同数据类型的列,只要值列的文本表示形式是目标类型的有效输入。这样,您可能会有不同类型的属性,并为各自的属性输出文本、日期、数字等。本文末尾有一个代码示例

小提琴

高级示例 -还演示了提到的额外列

\psql中的crosstabview Postgres 9.6将此元命令添加到其默认交互终端。您可以运行将用作第一个交叉表参数的查询,并立即或在下一步中将其提供给\crosstabview。比如:

db=> SELECT section, status, ct FROM tbl \crosstabview
与上面的结果类似,但它只是客户端的一个表示特性。输入行的处理略有不同,因此不需要ORDER BY。该页底部有更多的代码示例

psql特性的作者Daniel Vérité在dba.SE上的相关回答:

这本书已经过时了

函数crosstabtext、integer的变体已过时。忽略第二个整数参数。我引述:

交叉表文本sql,int N

crosstabtext的过时版本。参数N现在被忽略, 因为值列的数量始终由调用查询确定

不必要的铸造和重命名

如果一行没有所有属性,则失败。请参阅上面带有两个输入参数的安全变量,以正确处理缺少的属性

在交叉表的单参数形式中需要ORDER BY

在实践中,SQL查询应始终按1,2指定顺序,以确保 输入行的顺序是否正确


具有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
交叉表功能在tablefunc扩展下可用。您必须为数据库创建一次此扩展

创建扩展tablefunc

您可以使用以下代码使用交叉表创建透视表:


您缺少from子句,否则这是正确的。在我的系统上,解释计划大不相同——交叉表函数的成本为22.5,而左连接方法的成本约为其4倍,成本为91.38。它还产生大约两倍于其他连接类型的物理读取和执行哈希连接,这与其他连接类型相比可能非常昂贵。我已经对另一个答案投了赞成票,但是你的评论值得保留,所以我不会删除这个。如果你在交叉表查询中使用参数,你必须正确地转义它。示例:从上面说您只想要活动的:选择。。。从交叉表“选择节::文本、状态、计数::文本,其中状态=活动”,2为。。。注意双引号。如果用户在运行时将参数作为函数参数传递,例如,您可以说:SELECT。。。从交叉表“选择区段::文本、状态、计数::文本自t,其中状态=”| | par| U active | |,2为。。。这里有三个引号!。在BIRT中,这也适用于?占位符。有人能解释一下tablefunc模块中的交叉表函数为这个答案添加了什么吗?这个答案既可以完成手头的工作,而且在我看来更容易理解?@JohnBarça:这样一个简单的例子可以很容易地用case语句解决。但是,如果有更多的属性和/或其他数据,这会很快变得非常笨拙
类型而不仅仅是整数。顺便说一句:此表单使用聚合函数sum,最好使用min或max,而不使用其他也适用于文本的函数。但这与corosstab的效果略有不同,corosstab只使用每个属性的第一个值。没关系,只要只有一个。最后,性能也是相关的。CostStAB是用C编写的,并对任务进行了优化。@奥德丽,你没有运行相同的SQL吗?考虑添加解释,而只是在PostgreSQL中的一个代码块,因为某些原因,Table FUNC和交叉表没有被定义,并且我不允许定义它们。这个直观的解决方案对我来说很有效,所以振作起来+1,写得好,感谢您在实践中注意到SQL查询应始终按1,2指定顺序,以确保输入行的顺序正确。是否可以在交叉表查询中为列设置默认值?@Ashish:请开始一个新问题。评论不是地方。您可以随时链接到此链接以了解上下文。@ErwinBrandstetter这是另一个您以极其胜任、深思熟虑和易于理解的方式解释复杂事物的示例。如果有一个诺贝尔奖的帮助堆栈溢出你应该得到it@AndreSilva:同一集合的所有行必须具有相同的列类型。只需在一行中显式地强制转换就足够了,其余的就可以了。相关:;我有一个稍微不同的结构,发现这个例子有点难以理解,所以我记录了我的思考方式。也许它对任何人都有帮助。这个答案没有比已有的答案增加任何内容。谢谢,这帮了我解决了一个相关的问题。