我正在尝试在 pgsql 函数中创建并返回一个数据透视表。我遇到的问题是函数返回的列数取决于用户选择的日期范围。
我目前正在使用 colpivot 函数 ( https://github.com/hnsl/colpivot/blob/master/README.md ),这在标准查询中工作正常,但在函数中却不行,因为需要在调用时设置返回类型。
方法
第 1 步:
create temp table _test (
dt timestamp without time zone, id integer, NumericValue numeric
)
第 2 步:
insert into _test(dt , id ,NumericValue)
SELECT DISTINCT "T03017_PSR_LOG"."DateTime",
"T03017_PSR_LOG"."ID",
"T03017_PSR_LOG"."NumericValue"
FROM "T03017_PSR_LOG"
INNER JOIN "T03002_PSR_TAG_REG" ON "T03017_PSR_LOG"."TagID" = "T03002_PSR_TAG_REG"."TagID"
WHERE "T03017_PSR_LOG"."DateTime" > 2018-10-02 AND "T03017_PSR_LOG"."DateTime" < 2018-10-07,
ORDER BY "DateTime", "ID";
第 3 步:
select colpivot('_test_pivoted', 'select * from _test', array['tagid'], array['dt'], '#.numericvalue', null);
select * from _test_pivoted order by tagid;
如果我将上面的代码作为标准查询运行,它将返回如下内容:
ID 2018-10-03 2018-10-04 2018-10-05 2018-10-06
10 1405717.00 1453189.00 1499992.00 1546791.00
11 359102.00 371282.00 383042.00 395047.00
我需要类似上表的东西从函数返回,其中日期时间范围将是传递给函数的 2 个变量,但是我似乎无法找到解决方案,因为我不确定如何设置返回由于返回列的动态特性,请在函数顶部键入。
最佳答案
这可能看起来有点笨拙,但我不知道有什么方法可以返回可变数量的列,我认为最好的选择是使用数组。
在不了解您的数据的情况下,我只能假设您有数据缺口,这意味着并非每个 ID 都有每个日期的数据点,所以我要做的第一个任务是填补缺口并确定每个可能的日期组合和ID。
with all_dates as (
select distinct dt from _test
),
all_ids as (
select distinct id from _test
)
select id, dt
from all_dates
cross join all_ids
从那里,我将把它连接回原始数据集,这样每一行数组中的每个元素都指向同一事物(即,如果一行中的元素 #5 是 2017 年 11 月,那么这意味着对于每一行).
这是整个查询的样子:
with all_dates as (
select distinct dt from _test
),
all_ids as (
select distinct id from _test
),
all_combo as (
select id, dt
from all_dates
cross join all_ids
),
pivot_data as (
select
a.dt, a.id, coalesce (t.NumericValue, 0) as NumericValue
from
all_combo a
left join _test t on
a.id = t.id and
a.dt = t.dt
order by
a.id, a.dt
)
select
id, array_agg(NumericValue) as valuez
from pivot_data
group by id
这会有点重复(每一行都有相同的值),但您也可以将日期范围作为数组包含在内:
select
id, array_agg(dt) as dates, array_agg(NumericValue) as valuez
关于sql - Postgresql - 列数未知的数据透视表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52853112/