【问题标题】:How can I select a nested json object with a group by clause in oracle sql from a table?如何从表中选择带有 oracle sql 中的 group by 子句的嵌套 json 对象?
【发布时间】:2020-12-02 07:57:40
【问题描述】:

假设我有以下声明:

WITH t AS
(
  SELECT 'A' AS level_0, 'A1' AS level_1_1, 'object_1' AS level_1_2, 'A11' AS level_2_1, 'B11' AS level_2_2 FROM dual
  UNION ALL
  SELECT 'A' AS level_0, 'A1' AS level_1_1, 'object_1' AS level_1_2, 'A12' AS level_2_1, 'B12' AS level_2_2 FROM dual
  UNION ALL
  SELECT 'A' AS level_0, 'A1' AS level_1_1, 'object_1' AS level_1_2, 'A13' AS level_2_1, 'B13' AS level_2_2 FROM dual
  UNION ALL
  SELECT 'A' AS level_0, 'A1' AS level_1_1, 'object_1' AS level_1_2, 'A14' AS level_2_1, 'B14' AS level_2_2 FROM dual
  UNION ALL
  SELECT 'B' AS level_0, 'A1' AS level_1_1, 'object_2' AS level_1_2, 'A11' AS level_2_1, 'B15' AS level_2_2 FROM dual
  UNION ALL
  SELECT 'B' AS level_0, 'A1' AS level_1_1, 'object_2' AS level_1_2, 'A12' AS level_2_1, 'B16' AS level_2_2 FROM dual
  UNION ALL
  SELECT 'B' AS level_0, 'A1' AS level_1_1, 'object_2' AS level_1_2, 'A13' AS level_2_1, 'B17' AS level_2_2 FROM dual
)
SELECT * FROM t

我想要的输出如下所示:


+---------+---------------------------------------------------------------------------------+
| Level 0 |                                      JSON                                       |
+---------+---------------------------------------------------------------------------------+
| A       | {"level_1_1":"A1","object_1":{"A11":"B11","A12":"B12","A13":"B13","A14":"B14"}} |
| B       | {"level_1_1":"A1","object_2":{"A11":"B15","A12":"B16","A13":"B17"}}             |
+---------+---------------------------------------------------------------------------------+

如何使用 select 语句获得此输出?

非常感谢您的帮助!

【问题讨论】:

标签: sql json oracle oracle12c


【解决方案1】:

JSON_OBJECT()JSON_OBJECTAGG() 函数可以与适当的分组一起使用,例如

SELECT level_0,
       JSON_OBJECT(
                   'level_1_1' VALUE level_1_1,
                    level_1_2  VALUE JSON_OBJECTAGG(level_2_1 VALUE level_2_2)
        )
    AS "Result JSON"                           
  FROM t
 GROUP BY level_1_2, level_1_1, level_0

Demo

【讨论】:

    【解决方案2】:

    您可以使用GROUP BYLISTAGGconcatenation,如下所示:

    SQL> with t as(
      2  select 'A' as level_0, 'A1' as level_1_1, 'object_1' as level_1_2, 'A11' as level_2_1, 'B11' as level_2_2 from dual union all
      3  select 'A' as level_0, 'A1' as level_1_1, 'object_1' as level_1_2, 'A12' as level_2_1, 'B12' as level_2_2  from dual union all
      4  select 'A' as level_0, 'A1' as level_1_1, 'object_1' as level_1_2, 'A13' as level_2_1, 'B13' as level_2_2  from dual union all
      5  select 'A' as level_0, 'A1' as level_1_1, 'object_1' as level_1_2, 'A14' as level_2_1, 'B14' as level_2_2  from dual union all
      6  select 'B' as level_0, 'A1' as level_1_1, 'object_2' as level_1_2, 'A11' as level_2_1, 'B15' as level_2_2  from dual union all
      7  select 'B' as level_0, 'A1' as level_1_1, 'object_2' as level_1_2, 'A12' as level_2_1, 'B16' as level_2_2  from dual union all
      8  select 'B' as level_0, 'A1' as level_1_1, 'object_2' as level_1_2, 'A13' as level_2_1, 'B17' as level_2_2  from dual
      9  )
     10  select LEVEL_0,
     11     '{"level_1_1":"'|| level_1_1 || '","'||level_1_2 ||'":{'
     12     || LISTAGG('"' || level_2_1 || '":"' || level_2_2 || '"', ',')
     13  WITHIN GROUP (ORDER BY level_2_1, level_2_2)
     14     || '}}' AS JSON
     15  from  t
     16  GROUP BY LEVEL_0, level_1_1, level_1_2;
    
    LEVEL_0    JSON
    ---------- -------------------------------------------------------------------------------
    A          {"level_1_1":"A1","object_1":{"A11":"B11","A12":"B12","A13":"B13","A14":"B14"}}
    B          {"level_1_1":"A1","object_2":{"A11":"B15","A12":"B16","A13":"B17"}}
    
    SQL>
    

    【讨论】:

    • 非常感谢您的解决方案。我认为 listagg 函数中应该有一个分隔符参数,例如 LISTAGG('"' || level_2_1 || '":"' || level_2_2 || '"',',')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2011-06-14
    • 2022-09-29
    相关资源
    最近更新 更多