如何从postgresql中的状态转储创建timeseries CSV

如何从postgresql中的状态转储创建timeseries CSV,postgresql,Postgresql,鉴于这些数据: 创建表foo ts BIGINT不为空 数据JSONB不为空 ; 插入到foo值中 0,“[{host:alice,value:10},{host:bob,value:5}]”, 60,“[{host:alice,value:20},{host:bob,value:6}]”; 如何创建CSV输出,例如: 时间到了,爱丽丝,鲍勃 0,10,5 60,20,6 注意,我在查询时不知道alice和bob的情况 我试过交叉表,例如: 将视图foo_元素创建为 选择 ts, 元素->>“主

鉴于这些数据:

创建表foo ts BIGINT不为空 数据JSONB不为空 ; 插入到foo值中 0,“[{host:alice,value:10},{host:bob,value:5}]”, 60,“[{host:alice,value:20},{host:bob,value:6}]”; 如何创建CSV输出,例如:

时间到了,爱丽丝,鲍勃 0,10,5 60,20,6 注意,我在查询时不知道alice和bob的情况

我试过交叉表,例如:

将视图foo_元素创建为 选择 ts, 元素->>“主机”作为主机, 元素->>“值”作为值 从…起 选择 ts, jsonb_数组_元素数据作为元素 从富作为元素; 从交叉表中选择*作为ctts BIGINT、alice TEXT、bob TEXT; 输出:

 ts | alice | bob 
----+-------+-----
  0 | 10    | 5
 60 | 20    | 6
该查询唯一的错误是我必须硬编码主机的数量和名称,而且交叉表似乎只支持有限数量的列

我意识到我可以很容易地用代码在外部完成这项工作,在出现CSV时间线时组装它,然后在所有数据流传输完毕后将标题添加到顶部,但我希望在数据库中保留尽可能多的逻辑


我希望主机的数量是可管理的。与10-20类似。

SQL查询的一个基本限制是,在解析查询时执行查询之前,必须知道查询的所有列的数量、名称和数据类型。因此,没有硬编码列名的解决方法

但通常情况下,使用条件聚合比使用笨拙的

select f.ts,
       sum((item  ->> 'value')::int) filter (where d.item ->> 'host' = 'alice') as alice,
       sum((item  ->> 'value')::int) filter (where d.item ->> 'host' = 'bob') as bob
from foo f
  cross join jsonb_array_elements(data) as d(item)
group by f.ts
order by f.ts;  
如果主机的数量不经常更改,您可以考虑使用一个存储过程,定期为所有可用主机动态生成一个视图。大致如下:

做 $$ 声明 l_栏文本; l_sql文本; 开始 选择字符串\u aggformat'sumitem->>value::int filter,其中d.item->>host=%L为%I',host,host',' 进入l_列 从…起 选择不同的项目->>“主机”作为主机 来自富福 交叉连接jsonb_数组_元素数据作为数据项 T l_sql:=“创建视图主机_csv作为选择f.ts,| | l|列| | |”来自foo f交叉连接jsonb_数组_元素SF.data作为数据项组由f.ts”; 执行l_sql; 终止 $$;
使用colums是不可能的,但是使用数组是否有解决方案?不确定数组会有什么帮助。您如何知道哪个数组元素属于哪个主机?首先我可能会简化原始JSON,这样它就不是一个数组,而是直接包含主机名作为键,例如{bob:5,alice:20}