在 Postgres 9.6 中创建数据透视表 table
Create pivot table in Postgres 9.6
我在使用 SQL 创建所需的输出时遇到问题。我有一个事件 table,它保存了每个候选人参加的每个事件的记录,如下所示:
| 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 |
我可以从中创建一个枢轴 table 吗?我尝试使用交叉表扩展,但由于每个组(按 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);
使用过滤聚合通常是最简单的方法:
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;
我了解到您希望在旋转结果集中每个 id
的最新 asmnt
的 score
。
如果是,可以使用distinct on
获取每组最新的记录,然后条件聚合到pivot:
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
我在使用 SQL 创建所需的输出时遇到问题。我有一个事件 table,它保存了每个候选人参加的每个事件的记录,如下所示:
| 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 |
我可以从中创建一个枢轴 table 吗?我尝试使用交叉表扩展,但由于每个组(按 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);
使用过滤聚合通常是最简单的方法:
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;
我了解到您希望在旋转结果集中每个 id
的最新 asmnt
的 score
。
如果是,可以使用distinct on
获取每组最新的记录,然后条件聚合到pivot:
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