Postgresql 在Postgres中将列转换为行

Postgresql 在Postgres中将列转换为行,postgresql,pivot,crosstab,Postgresql,Pivot,Crosstab,我的表名是osk,st,item。osk字段为stid、stock、free、npr、itemno。st字段是stid,name。项目字段为id、name。我有多个模式。每个模式都有这个表 select i.name,st.name,stock,freestock from osk,st,items i where i.id=osk.itemno and st.stid=osk.stid 此查询返回如下结果 Name St.Name Stock FreeStock A

我的表名是
osk,st,item
。osk字段为
stid、stock、free、npr、itemno
。st字段是
stid,name
。项目字段为
id、name
。我有多个模式。每个模式都有这个表

select i.name,st.name,stock,freestock from osk,st,items i where i.id=osk.itemno 
and st.stid=osk.stid
此查询返回如下结果

  Name   St.Name    Stock   FreeStock
   A        B         10        20
   D        B         10        10
   C        E         12        10
但是我想要

 Name    B (stock)     B(Free)   E(Stock)  E (Free Stock)
  A        10           20         -           -
  D        10           10         -           -
  C        -            -          12          10
如何做到这一点。(我有多个架构。所有架构都有我要从所有架构检索的表)


我正在使用postgresql 9.3。如果可能,使用交叉表?如何使用它?

假设您有这样一个表(由于您没有提供确切的表定义,所以不得不猜测):

现在,您可以使用如下所述的
交叉表
功能:

其结果是:

 name | B (stock) | B (free) | E (stock) | E (free)
------+-----------+----------+-----------+----------
 A    |        10 |       20 |           |
 C    |           |          |        12 |       10
 D    |        10 |       10 |           |
(3 rows)

@Wolph先生,我认为这与那个例子有所不同?@Wolph请不要链接到Postgres的旧版本。使用
docs/current/static
而不是
docs/8.3/static
@IgorRomanchenko:Oops,似乎我错过了阅读,我以为我们在这里谈论的是Postgres 8.3,似乎是9.3:)我有一个疑问
从一些表中选择name,stname,stock
stock(name text,b int,e int)
b如何可能,先生。因为表中的stname是text。如何为多个schemas@SATSON:可以使用
b int
,因为
交叉表将结果拆分为列。你能澄清你在这里使用多个模式的意思吗?如果你说的是多个postgres模式,那么它只是简单地将它们添加到
搜索路径
或在表名前加前缀。如何获取多个模式中的所有数据。每个模式都有相同的表,但值不同。因此,如何获取所有模式值没有通用的方法,因为结果的列数是可变的,所以您需要在这里定义期望的列数/类别数。如果您需要它比您可能想考虑的每行返回而不是每列灵活。
create extension if not exists tablefunc;

select coalesce(stock.name, freestock.name) as name,
       stock.b as "B (stock)",
       freestock.b as "B (free)",
       stock.e as "E (stock)",
       freestock.e as "E (free)"
from 
    crosstab('
        select name,
            stname,
            stock
        from some_table
    ', '
        select distinct stname
        from some_table
        order by stname
    ') as stock(name text, b int, e int)
full outer join 
    crosstab('
        select name,
            stname,
            freestock
        from some_table
    ', '
        select distinct stname
        from some_table
        order by stname
    ') as freestock(name text, b int, e int)
on stock.name = freestock.name;
 name | B (stock) | B (free) | E (stock) | E (free)
------+-----------+----------+-----------+----------
 A    |        10 |       20 |           |
 C    |           |          |        12 |       10
 D    |        10 |       10 |           |
(3 rows)