我正在尝试使用 postgresql
中的 crosstab 函数来创建一个数据透视表
。但是,我很难理解如何在查询中构造我的 SQL。我的数据由四列组成,如下所示:
我使用以下代码创建此表:
CREATE TABLE ct(id SERIAL, zone_id int, group_id int, area double precision);
INSERT INTO ct(zone_id, group_id, area) VALUES(1,2,6798.50754160784);
INSERT INTO ct(zone_id, group_id, area) VALUES(1,3,10197.7613124118);
INSERT INTO ct(zone_id, group_id, area) VALUES(2,1,85708.8676744647);
INSERT INTO ct(zone_id, group_id, area) VALUES(2,2,56006.5971338327);
INSERT INTO ct(zone_id, group_id, area) VALUES(2,3,5584.33145616642);
INSERT INTO ct(zone_id, group_id, area) VALUES(2,5,8611.99732832252);
INSERT INTO ct(zone_id, group_id, area) VALUES(2,6,36103.5509183704);
INSERT INTO ct(zone_id, group_id, area) VALUES(2,8,9801.14541428806);
INSERT INTO ct(zone_id, group_id, area) VALUES(5,1,45796.0020793546);
并密切关注 postgresql
文档,我在我的 crosstab
查询中使用了以下代码:
SELECT *
FROM crosstab(
'select zone_id, group_id, area
from ct
')
AS ct(row_name integer,
g_1 double precision,
g_2 double precision,
g_3 double precision,
g_4 double precision,
g_5 double precision,
g_6 double precision,
g_7 double precision,
g_8 double precision);
这导致下表不是我想要的:
例如,在第二行中,我需要以下值:
85708.8676744647, 56006.5971338327, 5584.33145616642, NULL, 8611.99732832252, 36103.5509183704, NULL, 9801.14541428806
取而代之的是:
85708.8676744647, 56006.5971338327, 5584.33145616642, 8611.99732832252, 36103.5509183704, 9801.14541428806
但是,似乎忽略了null
值,以至于我的列名g1
到g8
,与原来的不对应团体。
最佳答案
使用 crosstab()
variant with two parameters :
SELECT * FROM crosstab(
'SELECT zone_id, group_id, area
FROM ct
ORDER BY 1,2'
,'SELECT g FROM generate_series(1,8) g' -- ! Provide values explicitly
)
AS ct(
row_name integer
, g_1 float8, g_2 float8
, g_3 float8, g_4 float8
, g_5 float8, g_6 float8
, g_7 float8, g_8 float8);
从而明确声明哪个值进入哪个输出列。所以该函数知道在哪里填写 NULL
值。在这种情况下,generate_series()
可以派上用场,它可以提供 8 行数字 1-8。 VALUES
表达式是一种替代方法:
'VALUES (1), (2), (3), (4), (5), (6), (7), (8)'
另外,不要忘记第一个参数查询中的 ORDER BY
子句。
关于sql - 如何在 postgresql 的 `tablefunc` 查询中包含空值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12885572/