【问题标题】:Postgresql - Pivot with Crosstab or alternative?Postgresql - 使用交叉表或替代方法进行透视?
【发布时间】:2026-02-07 16:15:01
【问题描述】:

我有下表:

我想对此进行旋转并得到以下结果:

  Table_name        Column_name      Values         ddmf_etl_id
"PROFITCENTERID"    "CO_AREA"       "DE02"           16807487
"PROFITCENTERID"    "PROFIT_CTR"    "0000001119"     16807487
"PROFITCENTERID"    "CO_AREA"       "DE02"           16807488
"PROFITCENTERID"    "PROFIT_CTR"    "0000001120"     16807488

很遗憾,由于 CROSSTAB 的参数数量有限 (3),我未能通过以下选择做到这一点:

SELECT  'PROFITCENTERID' AS table_name,t.*
FROM   

crosstab(

        'SELECT unnest(''{CO_AREA,PROFIT_CTR}''::text[]) AS col
             , row_number() OVER ()
             , unnest(ARRAY[CO_AREA::text,PROFIT_CTR::text]) AS val
        FROM   "1".PROFITCENTER_PROFITCENTERID'

   ) t (column_name text,  values text);

select 语句的结果(错误):

Postgresql 中是否有其他替代 Crosstab 的方法?或者也许可以用 Crosstab 做到这一点?

感谢任何帮助!谢谢!

【问题讨论】:

  • 将“转置”行作为单个 JSON 值返回的替代方案怎么样?与此类似:*.com/a/55160032

标签: postgresql pivot crosstab


【解决方案1】:

使用unnest() 将每行加倍并选择适当的值:

select
    'profitcenterid' as table_name,
    unnest(array['co_area', 'profit_ctr']) as column_name,
    unnest(array[co_area, profit_ctr]) as value,
    ddmf_etl_id as ddmf_etl_id
from profitcenter_profitcenterid

   table_name   | column_name |   value    | ddmf_etl_id 
----------------+-------------+------------+-------------
 profitcenterid | co_area     | de02       |    16807487
 profitcenterid | profit_ctr  | 0000001119 |    16807487
 profitcenterid | co_area     | de02       |    16807488
 profitcenterid | profit_ctr  | 0000001120 |    16807488
(4 rows)    

Live demo in rextester.

但是,这对于获得预期的 json 结果没有多大帮助。您想获取任意键名,因此无法根据子查询结果自动生成对象。它们可以使用原语jsonb_build_object() 创建:

select to_jsonb(s)
from (
    select
        'profitcenterid' as table_name,
        17 as type,
        '' as value,
        jsonb_build_array(
            jsonb_build_object('name', 'co_area', 'value', co_area, 'type', 0, 'children', '[]'::jsonb),
            jsonb_build_object('name', 'profit_ctr', 'value', profit_ctr, 'type', 0, 'children', '[]'::jsonb)
        ) as children
    from profitcenter_profitcenterid
    ) s

Example in rextester.

作为旁注,预期的结构似乎不必要地复杂,简单是一种美德。

【讨论】:

  • @pyme - 问题是预期的输出不是有效的 json,使用 jsonlint 来验证它。另外,请以文本格式提供您的查询和预期输出,例如在rextester.
  • jsonb 连接运算符 || exists. 递归合并参见 Merging JSONB values in PostgreSQL?
  • 你有几个问题,这里没有讨论的地方。问一个新问题。