【问题标题】:Return elements of Redshift JSON array on separate rows在单独的行上返回 Redshift JSON 数组的元素
【发布时间】:2015-07-23 14:46:24
【问题描述】:

我有一个如下所示的 Redshift 表:

 id | metadata
---------------------------------------------------------------------------
 1  | [{"pet":"dog"},{"country":"uk"}]
 2  | [{"pet":"cat"}]
 3  | []
 4  | [{"country":"germany"},{"education":"masters"},{"country":"belgium"}]
  • 所有数组元素只有一个字段。
  • 无法保证特定字段会出现在数组的任何元素中。
  • 字段名可以在数组中重复
  • 数组元素可以是任意顺序

我想取回一个如下所示的表格:

 id |   field   |  value
------------------------
 1  | pet       | dog
 1  | country   | uk
 2  | pet       | cat
 4  | country   | germany
 4  | education | masters
 4  | country   | belgium

然后我可以将它与我对输入表其余部分的查询结合起来。

我尝试过使用 Redshift JSON 函数,但无法在 Redshift 中编写函数/使用循环/拥有变量,我真的看不到这样做的方法!

如果我能澄清其他任何事情,请告诉我。

【问题讨论】:

    标签: json amazon-redshift


    【解决方案1】:

    CREATE VIEW seq_0_to_3 有通用版本。我们称之为CREATE VIEW seq_0_to_n。这可以由

    生成
    CREATE VIEW seq_0_to_n AS (  
        SELECT row_number() over (
                              ORDER BY TRUE)::integer - 1 AS i
        FROM <insert_large_enough_table> LIMIT <number_less_than_table_entries>);
    

    这有助于生成大序列作为视图。

    【讨论】:

      【解决方案2】:

      感谢这个启发 blog post,我已经能够制定一个解决方案。这是:

      1. 创建一个查找表以有效地“迭代”每个数组的元素。此表中的行数已等于或大于数组的最大元素数。假设这是 4(可以使用SELECT MAX(JSON_ARRAY_LENGTH(metadata)) FROM input_table 计算):

        CREATE VIEW seq_0_to_3 AS
            SELECT 0 AS i UNION ALL                                      
            SELECT 1 UNION ALL
            SELECT 2 UNION ALL    
            SELECT 3          
        );
        
      2. 由此,我们可以为每个 JSON 元素创建一行:

        WITH exploded_array AS (                                                                          
            SELECT id, JSON_EXTRACT_ARRAY_ELEMENT_TEXT(metadata, seq.i) AS json
            FROM input_table, seq_0_to_3 AS seq
            WHERE seq.i < JSON_ARRAY_LENGTH(metadata)
          )
        SELECT *
        FROM exploded_array;
        

        制作:

         id | json
        ------------------------------
         1  | {"pet":"dog"}
         1  | {"country":"uk"}
         2  | {"pet":"cat"}
         4  | {"country":"germany"}
         4  | {"education":"masters"}
         4  | {"country":"belgium"}
        
      3. 但是,我需要提取字段名称/值。由于我看不到使用 Redshift 的有限功能提取 JSON 字段名称的任何方法,因此我将使用正则表达式来执行此操作:

        WITH exploded_array AS (                                                                                       
            SELECT id, JSON_EXTRACT_ARRAY_ELEMENT_TEXT(metadata, seq.i) AS json
            FROM input_table, seq_0_to_3 AS seq
            WHERE seq.i < JSON_ARRAY_LENGTH(metadata)
        )
        SELECT id, field, JSON_EXTRACT_PATH_TEXT(json, field)
        FROM (
            SELECT id, json, REGEXP_SUBSTR(json, '[^{"]\\w+[^"]') AS field
            FROM exploded_array
        );
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-23
        • 2020-03-16
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        • 2018-05-28
        • 1970-01-01
        相关资源
        最近更新 更多