表架构
DROP TABLE bla;
CREATE TABLE bla (id INTEGER, city INTEGER, year_ INTEGER, month_ INTEGER, val INTEGER);
数据
INSERT INTO bla VALUES(1, 1, 2017, 1, 10);
INSERT INTO bla VALUES(2, 1, 2017, 2, 20);
INSERT INTO bla VALUES(3, 1, 2017, 1, 15);
INSERT INTO bla VALUES(4, 1, 2017, 2, 5);
INSERT INTO bla VALUES(5, 2, 2017, 1, 10);
INSERT INTO bla VALUES(6, 2, 2017, 2, 15);
INSERT INTO bla VALUES(7, 1, 2018, 1, 10);
INSERT INTO bla VALUES(8, 1, 2018, 1, 10);
我正在尝试聚合它们并将其置于数据透视表格式中,以便对于每个(city, year_)
组合,我会得到相应的总val
。以下是我可以从在线资源和官方文档中找到的信息。
SELECT * FROM crosstab (
'SELECT city, year_, month_, SUM(val) FROM bla GROUP BY 1, 2, 3 ORDER BY 1',
'SELECT DISTINCT month_ FROM bla ORDER BY 1'
) AS final_table (
city INTEGER,
year_ INTEGER,
january INTEGER,
February INTEGER
);
这是我现在得到的输出。
请注意缺少与组(city
1,year_
2018)对应的条目。我没有找到任何解决方案,并认为交叉表可能不支持这种级联结构。
我知道我可以创建一个临时变量(city_year_
)来绕过这个问题。
SELECT * FROM crosstab (
'SELECT CONCAT(city, year_)::text AS tag, month_, SUM(val) FROM bla GROUP BY 1, 2 ORDER BY 1',
'SELECT DISTINCT month_ FROM bla ORDER BY 1'
) AS final_table (
tag text,
january INTEGER,
February INTEGER
);
此处输出。
但相应列中的city
和year_
是我的首选格式(在视觉上更加丰富并保留原始数据 - 将tag
变量拆分为city
和{{1需要知道如何定义year_
。
非常感谢任何解决方案/帮助。问候。
答案 0 :(得分:1)
Postgres的crosstab()
期望源查询具有特定格式。
此语句[source sql]必须返回一个row_name列,一个类别列和一个值列。它也可能有一个或多个“额外”列。 row_name列必须是第一个。类别和值列必须是最后两列,按此顺序。 row_name和category之间的任何列都被视为“extra”。对于具有相同row_name值的所有行,“额外”列应该是相同的。
这里的问题是,您year_
和month_
两列都是row_name
列,而crosstab()
只允许一个row_name
列。因此,我们必须使用其他内容作为row_name
列。让我们使用这个函数dense_rank()
试试这个。
SELECT year_, city, january, february FROM crosstab (
'SELECT dense_rank() OVER (ORDER BY year_, city)::int AS row_name,
year_, city , month_, SUM(val) FROM bla GROUP BY city, year_, month_
ORDER BY 1',
'SELECT DISTINCT month_ FROM bla ORDER BY 1'
) AS final_table (
rowname integer,
year_ integer ,
city integer,
january INTEGER,
february INTEGER
);
这会产生所需的输出:
-------------------------------------
| year_ | city | january | february |
-------------------------------------
| 2017 | 1 | 25 | 25 |
-------------------------------------
| 2017 | 2 | 10 | 15 |
-------------------------------------
| 2018 | 1 | 20 | |
-------------------------------------