Postgres 查询嵌套的 JSONB
Postgres query nested JSONB
我有一个 JSONB
列包含 list
个 objects
。>
这是 table 架构:
column Name | Datatype
---------------------
timestamp | timestamp
data | JSONB
示例数据
1.
timestamp : 2020-02-02 19:01:21.571429+00
data : [
{
"tracker_id": "5",
"position": 1
},
{
"tracker_id": "11",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]
2.
timestamp : 2020-02-02 19:01:23.571429+00
data : [
{
"tracker_id": "7",
"position": 3
},
{
"tracker_id": "4",
"position": 2
}
]
3.
timestamp : 2020-02-02 19:02:23.571429+00
data : [
{
"tracker_id": "5",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]
我需要找到 tracker_id
从 position: 1
到 position: 2
的转换次数
此处,输出将是 2
,因为 tracker_id
4
和 5
将其 position
从 1
更改为 2
.
备注
转换应按升序排列,具体取决于 timestamp
position
更改不需要在连续的记录中。
我正在使用 timescaledb 扩展
到目前为止,我已经尝试查询单个记录列表中的对象,但我不确定如何合并每个记录的列表对象并进行查询。
对此的查询是什么?我应该写一个存储过程吗?
有多种函数可以帮助将多个数据库行组合成一个 JSON 结构:row_to_json()、array_to_json() 和 array_agg( ).
然后您将使用带有 ORDER BY 子句的常用 SELECT 来获取您想要的 timestamps/JSON 数据,并使用上述函数创建单个 JSON 结构。
我不使用 timescaledb 扩展,所以我会选择基于取消嵌套的纯 SQL 解决方案 json:
with t (timestamp,data) as (values
(timestamp '2020-02-02 19:01:21.571429+00', '[
{
"tracker_id": "5",
"position": 1
},
{
"tracker_id": "11",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]'::jsonb),
(timestamp '2020-02-02 19:01:23.571429+00', '[
{
"tracker_id": "7",
"position": 3
},
{
"tracker_id": "4",
"position": 2
}
]
'::jsonb),
(timestamp '2020-02-02 19:02:23.571429+00', '[
{
"tracker_id": "5",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]
'::jsonb)
), unnested as (
select t.timestamp, r.tracker_id, r.position
from t
cross join lateral jsonb_to_recordset(t.data) AS r(tracker_id text, position int)
)
select count(*)
from unnested u1
join unnested u2
on u1.tracker_id = u2.tracker_id
and u1.position = 1
and u2.position = 2
and u1.timestamp < u2.timestamp;
我有一个 JSONB
列包含 list
个 objects
。>
这是 table 架构:
column Name | Datatype
---------------------
timestamp | timestamp
data | JSONB
示例数据
1.
timestamp : 2020-02-02 19:01:21.571429+00
data : [
{
"tracker_id": "5",
"position": 1
},
{
"tracker_id": "11",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]
2.
timestamp : 2020-02-02 19:01:23.571429+00
data : [
{
"tracker_id": "7",
"position": 3
},
{
"tracker_id": "4",
"position": 2
}
]
3.
timestamp : 2020-02-02 19:02:23.571429+00
data : [
{
"tracker_id": "5",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]
我需要找到 tracker_id
从 position: 1
到 position: 2
的转换次数
此处,输出将是 2
,因为 tracker_id
4
和 5
将其 position
从 1
更改为 2
.
备注
转换应按升序排列,具体取决于 timestamp
position
更改不需要在连续的记录中。
我正在使用 timescaledb 扩展
到目前为止,我已经尝试查询单个记录列表中的对象,但我不确定如何合并每个记录的列表对象并进行查询。
对此的查询是什么?我应该写一个存储过程吗?
有多种函数可以帮助将多个数据库行组合成一个 JSON 结构:row_to_json()、array_to_json() 和 array_agg( ).
然后您将使用带有 ORDER BY 子句的常用 SELECT 来获取您想要的 timestamps/JSON 数据,并使用上述函数创建单个 JSON 结构。
我不使用 timescaledb 扩展,所以我会选择基于取消嵌套的纯 SQL 解决方案 json:
with t (timestamp,data) as (values
(timestamp '2020-02-02 19:01:21.571429+00', '[
{
"tracker_id": "5",
"position": 1
},
{
"tracker_id": "11",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]'::jsonb),
(timestamp '2020-02-02 19:01:23.571429+00', '[
{
"tracker_id": "7",
"position": 3
},
{
"tracker_id": "4",
"position": 2
}
]
'::jsonb),
(timestamp '2020-02-02 19:02:23.571429+00', '[
{
"tracker_id": "5",
"position": 2
},
{
"tracker_id": "4",
"position": 1
}
]
'::jsonb)
), unnested as (
select t.timestamp, r.tracker_id, r.position
from t
cross join lateral jsonb_to_recordset(t.data) AS r(tracker_id text, position int)
)
select count(*)
from unnested u1
join unnested u2
on u1.tracker_id = u2.tracker_id
and u1.position = 1
and u2.position = 2
and u1.timestamp < u2.timestamp;