繁体   English   中英

Oracle 12c Json 分体

[英]Oracle 12c Json split

这就是我在 Oracle 12c 中得到结果的方式

ID 开始日期范围 结束日期范围
1 [ "2019-01-07","2019-02-17","2019-03-17"] [ "2019-01-14","2019-02-21","2019-03-21"]

我想要它

ID 开始日期范围 结束日期范围
1 2019-01-07 2019-01-14
1 2019-02-17 2019-02-21
1 2019-03-17 2019-03-21

早些时候我问过单列拆分的这个问题,下面是链接如何替换特殊字符,然后在 oracle 中换行但是当我添加另一列时,就会出现笛卡尔积。

您可以使用json_table从 JSON arrays 中提取字符串,大概是实际日期:

select t.id, s.n, s.start_date, e.end_date
from your_table t
cross apply json_table (
  t.start_range, '$[*]'
  columns
    n for ordinality,
    start_date date path '$'
) s
join json_table (
  t.end_range, '$[*]' 
  columns
    n for ordinality,
    end_date date path '$'
) e
on e.n = s.n

for ordinality子句为每个数组提供一个索引,然后连接匹配“相关”数组条目。

ID |  N | START_DATE | END_DATE 
-: | -: | :--------- | :--------
 1 |  1 | 07-JAN-19  | 14-JAN-19
 1 |  2 | 17-FEB-19  | 21-FEB-19
 1 |  3 | 17-MAR-19  | 21-MAR-19

如果出于某种原因您想要字符串而不是日期,您可以更改列子句中的数据类型。

db<>小提琴

您也可以使用regexp_substr并在将[ , ]"替换为空格后进行connect by

模式和插入语句:

 create table testtable(Id int, Start_Date_Range varchar(500),  End_Date_Range varchar(500));

 insert into testtable values(1 ,'[ "2019-01-07","2019-02-17","2019-03-17"]',   '[ "2019-01-14","2019-02-21","2019-03-21"]');

询问:

 select distinct id, trim(regexp_substr(replace(replace(replace(Start_Date_Range,'"',''),'[',''),']',''),'[^,]+', 1, level) ) Start_Date_Range,
  trim(regexp_substr(replace(replace(replace(end_Date_Range,'"',''),'[',''),']',''),'[^,]+', 1, level) ) End_Date_Range,
  level
   from testtable
    connect by regexp_substr(Start_Date_Range, '[^,]+', 1, level) is not null
    order by id, level;

Output:

ID START_DATE_RANGE END_DATE_RANGE 等级
1 2019-01-07 2019-01-14 1
1 2019-02-17 2019-02-21 2
1 2019-03-17 2019-03-21 3

db<小提琴在这里

在对 OP 的评论中,我指出数据 model 不太正确。 两个JSON arrays中的值是相关的; 此类数据应编码为单个 object,而不是两个。 应该有一个对象数组,每个 object 有两个成员:开始日期和结束日期。

为了说明我建议的数据 model,我从一个示例输入表(带有额外的 id)开始,我完全按照 Alex Poole 的回答来生成 OP 询问的表,但随后我使用 JSON 生成函数来将数据放回 JSON 格式来说明我认为输入数据应该是什么样子。 (The provider of the JSON string should create a JSON in this format, rather than sending two separate JSON arrays of strings representing dates).

我在这里没有展示的是如何使用对JSON_TABLE的单个调用来从查询结束时创建的单个对象数组中拆分数据。 这比从两个单独的 JSON arrays 中获取数据的查询要简单得多。

注意 - 这不是一个真正的答案; 我将其写为答案,因为它显然不适合评论。

with
  t (id, start_date_range, end_date_range) as (
    select 1, '["2019-01-07","2019-02-17","2019-03-17"]',
              '["2019-01-14","2019-02-21","2019-03-21"]' from dual union all
    select 5, '["2020-04-23","2020-06-15"]',
              '["2020-04-30","2020-06-19"]'              from dual
  )
, shown_as_table(id, n, start_date, end_date) as (
    select t.id, s.n, to_char(s.start_date, 'yyyy-mm-dd'),
                      to_char(e.end_date, 'yyyy-mm-dd')
    from t
    cross apply json_table (
      t.start_date_range, '$[*]'
      columns
        n for ordinality,
        start_date date path '$'
    ) s
    join json_table (
      t.end_date_range, '$[*]' 
      columns
        n for ordinality,
        end_date date path '$'
    ) e
    on e.n = s.n
  )
select id, json_arrayagg(
                json_object('start' value start_date, 'end' value end_date)
                format json
                order by n
           ) as date_range_array
from   shown_as_table
group  by id
;

Output:

ID DATE_RANGE_ARRAY                                                                                                               
-- -------------------------------------------------------------------------------------------------------------------------------
 1 [{"start":"2019-01-07","end":"2019-01-14"},{"start":"2019-02-17","end":"2019-02-21"},{"start":"2019-03-17","end":"2019-03-21"}]                                 
 5 [{"start":"2020-04-23","end":"2020-04-30"},{"start":"2020-06-15","end":"2020-06-19"}]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM