我目前有一个以下格式的表id scenario period ct
2 1 1 1
2 1 2 1
2 1 3 1
2 1 4 1
2 2 1 1
2 2 2 1
2 2 3 1
2 2 4 1
2 3 1 1
2 3 2 1
2 3 3 1
2 3 4 1
:
id scenario period 1 2 3 4
2 1 1 1
2 1 2 1
2 1 3 1
2 1 4 1
2 2 1 1
2 2 2 1
2 2 3 1
2 2 4 1
2 3 1 1
2 3 2 1
2 3 3 1
2 3 4 1
我想创建下表:
crosstab()
已经在我的Postgres数据库中创建了tablefunc扩展。我目前正在尝试使用id scenario period 1 2 3 4
2 1 1 1 1 1 1
功能来完成支点。但是,我得到的表格如下所示:
SELECT * FROM crosstab(
'SELECT id, scenario, period, ct FROM m
ORDER BY 1',
'SELECT DISTINCT period FROM m
ORDER BY 1')
AS (id, scenario, period, 1, 2, 3, 4);
我试过的查询:
import csv
def parse_file(DATAFILE, lines):
with open(DATAFILE, 'r') as fd:
dat = csv.reader(fd)
header = next(dat) # makes strong assumption that csv has header
retval = list()
for index, row in enumerate(dat):
if (index >= lines): break # restricts number of lines
retval.append(dict(zip(header, row)))
return retval
d = parse_file(DATAFILE, 10)
答案 0 :(得分:4)
此查询生成所需的输出:
SELECT id, scenario, period, p1, p2, p3, p4 -- all except aux column rn
FROM crosstab(
'SELECT row_number() OVER (ORDER BY id, scenario, period)::int AS rn
, id, scenario, period, period, ct
FROM m
ORDER BY 1'
, 'VALUES (1), (2), (3), (4)'
) AS (rn int, id int, scenario int, period int, p1 int, p2 int, p3 int, p4 int);
两个特殊困难:
您还没有 row_name 的唯一列。我使用row_number()
生成代理键:rn
。我将其从外部SELECT
移除,以匹配您想要的结果
您尝试的方式,id
被视为 row_name ,所有输入行都聚合到一个输出行。
您希望结果中包含其他列(scenario
和period
),这些列必须位于 row_name 之后和类别之前。您必须列出period
两次以额外获取原始列 - 多余,就好像看起来一样。
基础:
与此特定案例相关:
通常,您会遇到如下查询:
SELECT id, scenario, p1, p2, p3, p4 -- all except aux column rn
FROM crosstab(
'SELECT rank() OVER (ORDER BY id, scenario)::int AS rn
, id, scenario, period, ct
FROM m
ORDER BY 1'
, 'VALUES (1), (2), (3), (4)'
) AS (rn int, id int, scenario int, p1 int, p2 int, p3 int, p4 int);
输出如下:
id scenario p1 p2 p3 p4
2 1 1 1 1 1
2 2 1 1 1 1
2 3 1 1 1 1
请注意,使用rank()
代替row_number()
将(id, scenario)
的相同组合组合在一起。
如果计数不是全部1
,则结果更有意义。