【问题标题】:Parse a JSON column with a FOR loop for every record?为每条记录解析一个带有 FOR 循环的 JSON 列?
【发布时间】: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 textno screen shotsEdit您的问题不要在 cmets 中发布代码
  • FOR 循环周围加上一个在表中循环的外部FOR 循环:FOR var1, var2, ... IN SELECT ... FROM ... LOOP
  • 感谢劳伦斯,这就是我最后所做的。我真的想知道是否有更好的方法来做到这一点。在答案中使用双 for 循环。
  • 我认为您的第一个“TABLE2”应该是“TABLE1”,因此冒昧地解决了这个问题。
  • 一个用于测试的示例 JSON 值会对这个问题有很大帮助。

标签: json postgresql for-loop plpgsql set-returning-functions


【解决方案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 数组,而不是您在问题中写的“列表”。

相关:

旁白

帮自己一个忙,避免在 Postgres 中出现双引号的 CaMeL 案例名称。在您的问题和答案中大量使用引用和 未引用 标识符只会造成混淆。我在您的问题中引用了列名,以在某种程度上与您的答案相匹配。我的长期建议:只使用合法的、小写的、不带引号的名称。

对于大多数工作负载,请考虑使用数据类型 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
    

    【讨论】:

    • 您的答案似乎建立在与您的问题中提出的完全不同的表格上......
    猜你喜欢
    • 1970-01-01
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多