为每条记录解析一个带有 FOR 循环的 JSON 列?
Posted
技术标签:
【中文标题】为每条记录解析一个带有 FOR 循环的 JSON 列?【英文标题】:Parse a JSON column with a FOR loop for every record? 【发布时间】:2018-05-27 11:40:44 【问题描述】:作为 Postgres 和 SQL 的新手,我在 Postgres 9.6 中有以下场景:
table1
"Myjson" JSON
"DateOfAcquisition" DATE
"Id" INT
在"Myjson"
中有一个列表,我用FOR
循环遍历它。
我的目标是将table1
中的每个json列表的元素放在另一个表中:
table2
jsonelem1 INT
jsonelem2 INT
"DateOfAcquisition" DATE
"Id" INT
我已经编写了以下代码来解析 json 字段,但我不确定如何为第一个表的每条记录运行 for
循环。
DO
$BODY$
DECLARE
omgjson json := myjsonfield; -- this should change for every row of the first table
i json;
myJsonelem1 INT;
myJsonelem2 INT;
begin
FOR i IN SELECT * FROM json_array_elements(omgjson)
loop
myJsonelem2 i->> 'jsonsubfield'::INT;
INSERT INTO destinationTable VALUES (myJsonelem2,DateOfAcquisition);
END LOOP;
END;
$BODY$ language plpgsql
【问题讨论】:
请edit您的问题并添加一些示例 JSON 数据和基于该数据的结果。Formatted text 请no screen shots。 Edit您的问题不要在 cmets 中发布代码 在FOR
循环周围加上一个在表中循环的外部FOR
循环:FOR var1, var2, ... IN SELECT ... FROM ... LOOP
。
感谢劳伦斯,这就是我最后所做的。我真的想知道是否有更好的方法来做到这一点。在答案中使用双 for 循环。
我认为您的第一个“TABLE2”应该是“TABLE1”,因此冒昧地解决了这个问题。
一个用于测试的示例 JSON 值会对这个问题有很大帮助。
【参考方案1】:
基于集合的方法通常比循环快得多(而且更短且不易出错)。
基于设置of your answer,这与您的问题有很大不同。
INSERT INTO table2(myfield, data) -- cleaner: explicit target columns
SELECT k."myField", j.i ->> 'data'
FROM table1 k, json_array_elements(k."ScrapedJson" -> 'calendar_days') j(i)
WHERE NOT k."HasBeenProcessed"
-- ORDER BY ??? -- you might want to order rows favorably?
隐式 LATERAL
连接是这里的关键技术。
... FROM table1 k, json_array_elements(...) ...
是:
... FROM table1 k
CROSS JOIN LATERAL json_array_elements(...) ...
显然,"ScrapedJson" -> 'calendar_days'
是一个 JSON 数组,而不是您在问题中写的“列表”。
相关:
What is the difference between LATERAL and a subquery in PostgreSQL?旁白
帮自己一个忙,避免在 Postgres 中出现双引号的 CaMeL 案例名称。在您的问题和答案中大量使用引用和 未引用 标识符只会造成混淆。我在您的问题中引用了列名,以在某种程度上与您的答案相匹配。我的长期建议:只使用合法的、小写的、不带引号的名称。
Are PostgreSQL column names case-sensitive?对于大多数工作负载,请考虑使用数据类型 jsonb
而不是 json
。
【讨论】:
【参考方案2】:感谢劳伦斯,这里是任何感兴趣的人的解决方案。
我想知道,有没有更好的方法?
DO
$BODY$
DECLARE
i json;
k RECORD;
mydata INT;
begin
FOR k IN SELECT * from TABLE1 where "HasBeenProcessed" = FALSE
LOOP
FOR i IN SELECT * FROM json_array_elements(k."ScrapedJson" -> 'calendar_days')
LOOP
mydata = i->> 'data';
INSERT INTO "Table2" VALUES (k."myField",mydata);
END LOOP;
end LOOP;
END;
$BODY$ language plpgsql
【讨论】:
您的答案似乎建立在与您的问题中提出的完全不同的表格上......以上是关于为每条记录解析一个带有 FOR 循环的 JSON 列?的主要内容,如果未能解决你的问题,请参考以下文章
PLpgSQL:将每条记录存储在 For Loop 中并返回 json