[英]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
如果出于某种原因您想要字符串而不是日期,您可以更改列子句中的数据类型。
您也可以使用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.