在 Postgres 中聚合 jsonb 数据

问题描述 投票:0回答:1

我在数据库表中有一个 jsonb 字段,其中包含以下数据:

{"access": {
  "D2024.06.13": [{"qty": 1, "time": "12:05"}, {"qty": 3, "time": "12:32"}],
  "D2024.06.14": [{"qty": 1, "time": "08:37"}]
}}

我想按 10 分钟时段(00:00 至 23:50)按日期和时间对数据进行分组

所以

2024.06.13
12:00 : 1
12:10 : 0
12:20 : 0
12:30 : 3
12:40 : 0
...

{'2024.06.13' : {'12:00':1, '12:10':0, '12:20':0, '12:30':3, '12:40':0 ....}, '2024.06.13' : {'12:00':1 ....}

这样我之后就可以画出时间表了。

postgresql jsonb
1个回答
0
投票

分多个步骤:

  1. 使用示例数据创建表:
create table mytable as 
( select 1 as x, '{"access": {
  "D2024.06.13": [{"qty": 1, "time": "12:05"}, {"qty": 3, "time": "12:32"}],
  "D2024.06.14": [{"qty": 1, "time": "08:37"}]
}}'::jsonb as j);
  1. 获取天数
with nrofDays as (
   select 
      min(substr(key,2,10)::date) as fromdate, 
      max(substr(key,2,10)::date) as todate,
      max(substr(key,2,10)::date) - min(substr(key,2,10)::date)+1 as count
   from 
      mytable, 
      jsonb_each(j->'access')
)
SELECT * FROM nrofDays
自日期 今天
2024-06-13 2024-06-14 2
  1. 选择所有 10 分钟间隔:
with nrofDays as (
   select 
      min(substr(key,2,10)::date) as fromdate, 
      max(substr(key,2,10)::date) as todate,
      max(substr(key,2,10)::date) - min(substr(key,2,10)::date)+1 as count
   from 
      mytable, 
      jsonb_each(j->'access')
)
,timescale as (
   select ((select fromdate from nrofDays) + '00:00'::time + interval '1 minute' * t) as tim 
   from generate_series(0,(24*60*(select count from nrofDays)),10) t
)
select * from timescale
蒂姆
2024-06-13 00:00:00.000
2024-06-13 00:10:00.000
2024-06-13 00:20:00.000
2024-06-13 00:30:00.000
2024-06-13 00:40:00.000
2024-06-13 00:50:00.000
2024-06-13 01:00:00.000
2024-06-13 01:10:00.000
...
2024-06-14 23:20:00.000
2024-06-14 23:30:00.000
2024-06-14 23:40:00.000
2024-06-14 23:50:00.000
2024-06-15 00:00:00.000
  1. 标准化方式选择您的数据(无 json 列):
  select 
   x,
   substring(key,2,10)::date as dat,
   (value->>'time')::time as tim,
   substring(key,2,10)::date + (value->>'time')::time as dt 
from 
(select x, key, value as v1
    from 
        mytable, 
        jsonb_each(j->'access') 
    ) x,
    jsonb_array_elements(v1)
x 数据 蒂姆 dt
1 2024-06-13 12:05:00 2024-06-13 12:05:00.000
1 2024-06-13 12:32:00 2024-06-13 12:32:00.000
1 2024-06-14 08:37:00 2024-06-14 08:37:00.000
  1. 选择第 2 步中的数据,并将其与第 3 步中的结果左连接
with nrofDays as (
   select 
      min(substr(key,2,10)::date) as fromdate, 
      max(substr(key,2,10)::date) as todate,
      max(substr(key,2,10)::date) - min(substr(key,2,10)::date)+1 as count
   from 
      mytable, 
      jsonb_each(j->'access')
)
,timescale as (
   select ((select fromdate from nrofDays) + '00:00'::time + interval '1 minute' * t) as tim 
   from generate_series(0,(24*60*(select count from nrofDays)),10) t
)
select 
   timescale.tim,
   count(x)
from timescale
left join 
   (
   select 
   x,
   substring(key,2,10)::date as dat,
   (value->>'time')::time as tim,
   substring(key,2,10)::date + (value->>'time')::time as dt 
from 
(select x, key, value as v1
    from 
        mytable, 
        jsonb_each(j->'access') 
    ) x,
    jsonb_array_elements(v1)
) d on d.dt between timescale.tim and timescale.tim + interval '1 minute' * 10 
group by timescale.tim
order by timescale.tim

MOTE:所选日期始终从“00:00”开始,因此当您希望第一天从“12:05”开始时,您可能需要进行一些调整,但我将其留给您😉

参见:DBFIDDLE

© www.soinside.com 2019 - 2024. All rights reserved.