You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL行转列实现求助:将指定数据集转为宽表

实现PostgreSQL行转列的两种实用方法

嗨,针对你这个行转列的需求,在PostgreSQL里有两种很靠谱的实现方式,我给你详细拆解说明:

方法一:条件聚合(通用SQL方案)

这种方法不需要依赖任何扩展,几乎所有SQL数据库都支持,逻辑直观易懂,适合简单的行转列场景:

WITH data AS (
    SELECT * FROM (
        VALUES 
            ('2018-08-09'::date,'cancel',35), 
            ('2018-08-09'::date,'sum',25), 
            ('2018-08-09'::date,'count',10) 
    ) AS v(date, type, number)
)
SELECT 
    date,
    MAX(CASE WHEN type = 'cancel' THEN number END) AS cancel,
    MAX(CASE WHEN type = 'sum' THEN number END) AS sum,
    MAX(CASE WHEN type = 'count' THEN number END) AS count
FROM data
GROUP BY date;

逻辑说明:

  • 用CASE语句针对每种type筛选出对应的number值;
  • 因为每个date + type组合只有一条数据,用MAX/MIN/SUM聚合都可以,这里用MAX只是为了把筛选后的值聚合到同一行;
  • 最后按date分组,就能得到你想要的列转行结果。

方法二:使用PostgreSQL专属的crosstab函数(高性能方案)

如果要处理大数据量的行转列,PostgreSQL的tablefunc扩展提供的crosstab函数性能会更优,步骤如下:

首先需要启用tablefunc扩展(只需要执行一次):

CREATE EXTENSION IF NOT EXISTS tablefunc;

然后编写行转列查询:

WITH data AS (
    SELECT * FROM (
        VALUES 
            ('2018-08-09'::date,'cancel',35), 
            ('2018-08-09'::date,'sum',25), 
            ('2018-08-09'::date,'count',10) 
    ) AS v(date, type, number)
)
SELECT * FROM crosstab(
    -- 源查询:必须按分组列(date)和行标识列(type)排序
    'SELECT date, type, number FROM data ORDER BY 1,2',
    -- 指定要转成列的type值列表
    'SELECT unnest(''{"cancel","sum","count"}''::text[])'
) AS ct(date date, cancel int, sum int, count int);

逻辑说明:

  • 第一个参数是源数据的查询语句,必须按分组列和行标识列排序,保证数据顺序正确;
  • 第二个参数定义了要转成列的所有type值;
  • 最后AS ct(...)部分需要明确指定结果集的列名和数据类型,要和第二个参数的顺序一一对应。

两种方法最终都会输出你想要的结果:

datecancelsumcount
2018-08-09352510

内容的提问来源于stack exchange,提问作者melik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:41:53