使用 INNER JOIN LATERAL 和 postgresql 将宽表转换为长表

Posted

技术标签:

【中文标题】使用 INNER JOIN LATERAL 和 postgresql 将宽表转换为长表【英文标题】:Transform wide table to long using INNER JOIN LATERAL and postgresql 【发布时间】:2016-06-27 08:42:09 【问题描述】:

使用 postgresql,我尝试将表 1(宽格式)中的数据转换/透视到长格式的新目标表 2,但没有成功:

我的问题的简化示例:

表一

id_profil  | no_h |  P1 |   P2 |   P3 |  Pn
01              1     5      7     x1   ...
01              2     7     78     x2   ...
02              1     5      7     x3   ...

表2,表1转换结果:

id_profil    | no_h |  parametre   |      valeur 
01                1           P1               5
01                1           P2               7 
01                1           P3              x1 
01                2           P1               7    
01                2           P2              78    
01                2           P3              x2    
02                1           P1               5   
02                1           P2               7
02                1           P3              x3    

您可以在this sqlfiddle 中找到并使用表 1 结构/数据。

我在一些 *** 帖子中看到可以使用 INNER JOIN LATERAL 来做到这一点。 (参见Postgres analogue to CROSS APPLY in SQL Server。)但是如何将正确的列名注入参数列?

更新

在真实的数据库中,我有超过 150 列,所以如果可以不在查询中手动输入每个列名,那可能会更好。

【问题讨论】:

unpivot and PostgreSQL的可能重复 【参考方案1】:

您必须为 valeur 列使用 CASE 并将其转换为通用类型(例如文本)以及参数名称列表:

with 
  table1(id_profil, no_h, parametre1, parametre2, parametre3) as (
    VALUES (01, 1, 5, 7, 'x1'::text), 
           (01, 2, 7, 78, 'x2'), 
           (02, 1, 5, 7, 'x3')
    ),
  col as (
    unnest('parametre1,parametre2,parametre3'::text[])
    )
select t.id_profil, t.no_h, col as parametre,
       case col when 'parametre1' then t.parametre1::text
                when 'parametre2' then t.parametre2::text
                when 'parametre3' then t.parametre3::text
       end as valeur
from col
cross join table1 t
order by 1, 2, 3

【讨论】:

感谢您的第一个答案和赞成票,我更新了我的问题,因为我没有指定在我的真实基地中我有超过 150 列,所以我无法输入每个列... @reyman64 您可以使用 pg_attribute 创建 col 表和 CASE 部分,并使用 RETURN QUERY EXECUTE 动态执行查询。 Hum thx,我不是专家,我尝试在网络上使用 QUERY EXECUTE 搜索动态 CASE 的示例。

以上是关于使用 INNER JOIN LATERAL 和 postgresql 将宽表转换为长表的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy ORM:LEFT JOIN LATERAL()正确

即使使用 INNER JOIN 而不是 IN,MySQL 查询也非常慢

SQL-连接查询:left join,right join,inner join,full join之间的区别

SQL中inner join,outer join和cross join的区别

SQLServer中 join 跟inner join的区别是啥?

SQL中inner join,outer join和cross join的区别