在 Postgres 9.6 中创建数据透视表

Posted

技术标签:

【中文标题】在 Postgres 9.6 中创建数据透视表【英文标题】:Create pivot table in Postgres 9.6 【发布时间】:2020-10-22 09:22:41 【问题描述】:

我无法使用 SQL 创建所需的输出。我有一个事件表,其中包含每个候选人参加的每个事件的记录,如下所示:

| id | asmnt   | timestamp           | score |
|----|---------|---------------------|-------|
| 1  | pushups | 2020-06-21 12:31:12 | 34    |
| 1  | situps  | 2020-06-21 13:31:12 | 65    |
| 1  | run     | 2020-06-22 12:31:12 | 901   |
| 1  | pullups | 2020-06-21 14:31:12 | 15    |
| 2  | pushups | 2020-06-21 12:31:12 | 13    |
| 2  | situps  | 2020-06-21 13:31:12 | 21    |
| 2  | run     | 2020-06-22 12:31:12 | 1401  |
| 2  | pullups | 2020-06-21 14:31:12 | 3     |
| 2  | pushups | 2020-06-23 12:31:12 | 31    |
| 2  | situps  | 2020-06-23 13:31:12 | 45    |
| 2  | run     | 2020-06-24 12:31:12 | 1101  |
| 2  | pullups | 2020-06-23 14:31:12 | 13    |

我可以从中创建一个数据透视表吗?我尝试使用交叉表扩展,但由于每个组(按 id)的大小不同,我收到一个错误(不足为奇)。保留顺序 (asmnt) 以及按时间戳排序很重要。

这是我想要的输出:

| id | pushups | situps | run | pullups |
|----|---------|--------|-----|---------|
| 1  | 34      | 65     | 901 |   15    |
| 2  | 31      | 45     | 1101|   13    |

这是我尝试过的 SQL(asmnt:APFPS、APFSU、APF2M 或 APFPL):

select *
from crosstab('select brandi_id, asmnt_code, score
from event
where left(asmnt_code,3) = ''APF''
order by brandi_id, asmnt_code, event_timestamp') 
    as events(brandi_id INTEGER,APF2M TEXT,APFPL TEXT,APFPS TEXT,APFSU TEXT,score INTEGER);

【问题讨论】:

请显示您想要的结果,以及您当前的尝试(即使它出错)。 对不起!我添加了所需的输出以及到目前为止我尝试过的内容。谢谢! 【参考方案1】:

我了解您希望在旋转的结果集中根据 id 获取最新的 asmntscore

如果是这样,您可以使用distinct on 来获取每个组的最新记录,然后进行条件聚合来透视:

select
    id,
    max(score) filter(where asmnt = 'pushups') pushups,
    max(score) filter(where asmnt = 'situps') situps,
    max(score) filter(where asmnt = 'run') run,
    max(score) filter(where asmnt = 'pullups') pullups
from (
    select distinct on (id, asmnt) e.*
    from event e
    order by id, asmnt, timestamp desc
) e
group by id

【讨论】:

【参考方案2】:

使用过滤聚合通常是最简单的方法:

select id, 
       count(*) filter (were asmnt = 'pushups') as pushups,
       count(*) filter (were asmnt = 'situps') as situps,
       count(*) filter (were asmnt = 'run') as run,
       count(*) filter (were asmnt = 'pullups') as pullups
from event
group by id;

【讨论】:

以上是关于在 Postgres 9.6 中创建数据透视表的主要内容,如果未能解决你的问题,请参考以下文章

在 sql 中创建一个带联接的数据透视表

在 LibreOffice Base 中创建等效数据透视表的 SQL (HSQLDB) 查询

在R中创建“数据透视表”,每行填充因子值

如屏幕截图中所述,我想在 SQL 中创建一个数据透视表 [重复]

postgres:从命令行在数据库中创建表

数据库更改日志表未在 Liquibase 的 Postgres 环境中创建