如何从JSON中提取数据到表格格式,除了_id之外没有任何引用。
我有一个下面的表和JSON数据。
create table jsobdata(
id serial,
j_data jsonb)
insert into jsobdata (j_data) values('{"count":1,"next":null,"previous":null,"results":[{"_id":128,"start":"2023-06-13T19:01:20.952+05:30","end":"2023-06-13T19:01:43.804+05:30","username":"nayan","Output_1/surveyname":"A1","Output_1/thematic":"A2","Output_1/State":"DC","Output_1/Month":"06","Output_1/Quarter":"2","Output_1/QuarterText":"Q2","Output_1/Suboutput_1_3/RRF_3/Question_3/Question_3__1/Q2Target_3":"29","_submitted_by":"nayan"}]}');
- 输出格式如下表所示。**
| _id|指示器|价值|
| - -----|- -----|- -----|
| 一百二十八|启动|2023 - 06 - 13T19:01:20.952 + 05:30|
| 一百二十八|结束|2023 - 06 - 13T19:01:43.804 + 05:30|
| 一百二十八|用户名|纳扬|
| 一百二十八|Output_1/surveyname| A1|
| 一百二十八|Output_1/专题|A2|
| 一百二十八|输出_1/状态|直流|
| 一百二十八|输出_1/月|06|
| 一百二十八|输出_1/季度|02|
| 一百二十八|Output_1/QuarterText| Q2|
| 一百二十八|输出_1/子输出_1_3/RRF_3/问题_3/问题_3__1/Q2Target_3|二十九|
| 一百二十八|提交人|纳扬|
1条答案
按热度按时间nnt7mjpx1#
在PostgreSQL中,可以使用jsonb_each_text函数从JSON列中提取数据,该函数将最外层的JSON对象扩展为一组键值对。jsonb_array_elements和jsonb_each_text的组合使用将允许您在数组中提取嵌套的JSON对象。
下面是你如何实现这一点:
这个查询首先从j_data列中提取'results'数组。然后,它扩展该数组中的每个JSON对象,并为这些JSON对象中的每个对象进一步将它们扩展为键值对。这将为每个键值对提供一行,正如您所希望的那样。
但是,请记住,此查询不会正确处理更深层次的嵌套JSON对象。如果JSON对象可以有任意层次的嵌套,则需要使用递归查询,这可能非常复杂。
另外,请记住,这样的操作在性能方面可能代价很高。因此,如果经常需要以结构化的、类似表的格式对数据进行操作,那么可能值得考虑将其存储在规范化的关系表中而不是JSONB中。
考虑到更新后的问题,答案应该保持不变。但是,提供的JSON对象似乎有一些嵌套属性。所提供的查询仅适用于JSON对象顶层的属性,而不适用于嵌套的属性,如“Output_1/surveyname”。
不幸的是,Postgres没有提供一种开箱即用的方法来将嵌套的JSON对象扁平化为一组键值对。如果您可以控制传入JSON的结构,最简单的解决方案是避免嵌套属性。
如果不能更改JSON的结构,则需要编写一个递归函数或一系列命令来处理嵌套的属性。这可能会变得非常复杂,如果您有大量数据,可能无法很好地执行。
考虑以下解决方案:
这是一个相当高级的查询。它使用递归公共表表达式(CTE)来处理嵌套的JSON对象。它首先像前面的查询一样提取顶级属性,但是如果遇到嵌套的JSON对象,它只是将其转换为字符串(使用::文本转换),而不是尝试提取其属性。
请注意,这是一种过于简单的方法,可能无法完全满足您的需求。例如,它不处理JSON中的数组,它将嵌套对象转换为字符串,而不是将它们扁平化。如果你需要处理这些更复杂的情况,你可能需要编写更复杂的递归函数,或者考虑使用具有更好JSON处理能力的语言(如Python或JavaScript)来处理数据,然后再将数据插入数据库。
此外,请记住,这种方法对于大量数据来说性能不佳。如果您经常需要以结构化的方式对JSON数据进行操作,那么首先以更结构化的格式存储数据可能会更好。