ORACLE JSON_TABLE 我需要从数组中获取 2 列

Posted

技术标签:

【中文标题】ORACLE JSON_TABLE 我需要从数组中获取 2 列【英文标题】:ORACLE JSON_TABLE I need to get 2 columns from an array 【发布时间】:2020-12-13 21:36:48 【问题描述】:

我有这个 SQL 代码

SELECT * FROM JSON_TABLE (('
[
    "tipodenunciaid": [1,2],
    "municipioid": [1,2]
]
'), '$[*]' COLUMNS (tipodenunciaid integer PATH '$.tipodenunciaid[*]', municipioid integer PATH '$.municipioid[*]'));

我想得到下一个结果:

我的查询有什么问题?

非常感谢。

【问题讨论】:

输入和输出是如何关联的? municipioid 的值 45 发生了什么? 输出只是我需要结构的一个例子。 您需要向我们展示您想要的特定数据的实际输出。否则就不清楚你到底在追求什么。 我只需要这 2 个数组变成 2 列.. 你不能单独使用 JSON 函数来做到这一点——原因很简单,JSON 结构对单独属性的数组值没有意义。最大的问题是您的输入数据,而不是您的查询。如果这些值应该与您在输出中显示的那样相关,那么 JSON 应该是一个对象数组,每个对象都具有您在 your JSON 中的顶层所具有的两个属性。按照您现在获取数据的方式,您需要将数组值提取到两个单独子查询中的列中,然后按序数连接。 【参考方案1】:

你不能这样使用json_table()。如果您希望两个数组不嵌套在不同的列中,并根据每个数组中每个元素的位置排列,那么一种选择是将每个数组分别扩展为行,使用ordinality 跟踪每个元素的位置,然后加入两个结果集。 full join 可以方便地容纳每个数组中不相等数量的元素:

with 
    data as (
        select ' "tipodenunciaid": [1,2,3,4], "municipioid": [1,2,3,4,5] ' as js from dual
    ),
    t as (
        select t.*
        from data d
        cross apply json_table(
            d.js,
            '$.tipodenunciaid[*]' columns (rn for ordinality, tipodenunciaid integer path '$')
        ) t
    ),
    m as (
        select m.*
        from data d
        cross apply json_table(
            d.js,
            '$.municipioid[*]' columns (rn for ordinality, municipioid integer path '$')
        ) m
    )
select t.tipodenunciaid, m.municipioid
from t
full join m on m.rn = t.rn

Demo on DB Fiddle.

【讨论】:

【参考方案2】:

您可以使用两个OUTER APPLYs 和FOR ORDINALITY 来生成数组的纵坐标以将表连接到自身:

SELECT j.id,
       CASE
       WHEN t.id = m.id OR t.id > m.max_id OR m.id IS NULL
       THEN tipodenunciaid
       END AS tipodenunciaid,
       CASE
       WHEN t.id = m.id OR m.id > t.max_id OR t.id IS NULL
       THEN municipioid
       END AS municipioid
FROM   table_name j
       OUTER APPLY (
         SELECT id,
                tipodenunciaid,
                MAX(id) OVER () AS  max_id
         FROM   JSON_TABLE(
                  j.json,
                  '$.tipodenunciaid[*]'
                  COLUMNS (
                    id FOR ORDINALITY,
                    tipodenunciaid integer PATH '$'
                  )
                )
       ) t
       OUTER APPLY (
         SELECT id,
                municipioid,
                MAX(id) OVER () AS  max_id
         FROM   JSON_TABLE(
                  j.json,
                  '$.municipioid[*]'
                  COLUMNS (
                    id FOR ORDINALITY,
                    municipioid integer PATH '$'
                  )
                )
       ) m
WHERE  t.id = m.id
OR     t.id IS NULL
OR     ( m.id > t.max_id AND t.id = t.max_id )
OR     m.id IS NULL
OR     ( t.id > m.max_id AND m.id = m.max_id );

其中,对于样本数据:

CREATE TABLE table_name ( id, json ) AS
SELECT 1, '"tipodenunciaid":[1,2],"municipioid":[1,2]' FROM DUAL UNION ALL
SELECT 2, '"tipodenunciaid":[],"municipioid":[3,4]' FROM DUAL UNION ALL
SELECT 3, '"tipodenunciaid":[5],"municipioid":[]' FROM DUAL UNION ALL
SELECT 4, '"tipodenunciaid":[6,7],"municipioid":[6]' FROM DUAL UNION ALL
SELECT 5, '"tipodenunciaid":[8],"municipioid":[8,9]' FROM DUAL;

输出:

身份证 | TIPODENUNCIAID | MUNICIPIOID -: | -------------: | ----------: 1 | 1 | 1 1 | 2 | 2 2 | | 3 2 | | 4 3 | 5 | 4 | 6 | 6 4 | 7 | 5 | 8 | 8 5 | | 9

db小提琴here

【讨论】:

以上是关于ORACLE JSON_TABLE 我需要从数组中获取 2 列的主要内容,如果未能解决你的问题,请参考以下文章

oracle表单12c中的Json_table函数

ORACLE 将json数组转成表

oracle sql中的JSON_TABLE未捕获嵌套的json数据

JPA 标准 API 和 Oracle JSON_TABLE 函数

MySql 5.7对json_table()函数的一次变通替代

Oracle SQL:JSON 表;获取数组的大小