在其中一个专栏中,我以文本格式存储JSON数据。示例数据如下所示:
{
"dummy_time": "2016-04-27T18:44:55+00:00",
"timeout_data": "2016-04-29T16:22:35+00:00,2016-04-30T16:22:35+00:00,2016-05-29T16:22:35+00:00",
"time_id": "T101",
"time_desc": "bla bla bla"
}
我需要编写SQL查询来查找此列有多个密钥timeout_data日期的行。我对REGEX并不是那么好。我编写了简单的查询来查找关键timeout_data中的两个日期:
SELECT *
FROM table1 f
WHERE REGEXP_LIKE(f.data, '.+\"timeout_data\": \".+,.+\",\"time_id\".*')
AND ROWNUM<6;
这个查询已经运行了很久。表有大约35,000,000行。 我不确定如何在密钥timeout_data中找到多个日期。如果您需要更多信息,请与我们联系。
答案 0 :(得分:0)
也许instr()
会更快。
SELECT 'test'
FROM (SELECT '{
"dummy_time": "2016-04-27T18:44:55+00:00",
"timeout_data": "2016-04-29T16:22:35+00:00,2016-05-29T16:22:35+00:00",
"time_id": "T101",
"time_desc": "bla bla bla"
}' data FROM dual)
WHERE instr(data,',',instr(data,'"timeout_data"')) < instr(data,'"',instr(data,'"timeout_data"'),4);
您可以在数据的子集上进行测试。此外,instr(data,'"timeout_data"')
被使用了两次,可能将其分解将加速该过程。
更新:您的REGEX似乎有问题 - 需要在.+
之前\"time_id\"
此外 - REGEX不是限制因素。在我的机器上,一个100k SELECT .. FROM dual循环需要4.3秒。增加REGEX需要0.1秒。
答案 1 :(得分:0)
1)使用timeout_data
提取行2)计算模式的出现次数。
select REGEXP_COUNT(regexp_substr(json,'^.*timeout_data.*$', 1,1,'m'), '\d{4}-\d{2}-\d{2}T')
from (
select '{
"dummy_time": "2016-04-27T18:44:55+00:00",
"timeout_data": "2016-04-29T16:22:35+00:00,2016-04-30T16:22:35+00:00,2016-05-29T16:22:35+00:00",
"time_id": "T101",
"time_desc": "bla bla bla"
}' json from dual
);
答案 2 :(得分:0)
您可以使用正则表达式找到ISO8601格式的日期:
\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}
如果您想要多个以逗号分隔的副本,那么您可以使用:
pattern(,pattern)+
(如果您只想找到两个匹配项,请删除尾随+
)
所以
\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}(,\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2})+
哪会使您的查询:
SELECT *
FROM table1 f
WHERE REGEXP_LIKE(f.data, '"timeout_data":\s*"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}(,\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2})+"')
AND ROWNUM<6;
但是,如果您不想专门匹配日期,只想测试是否有多个以逗号分隔的值,那么您可以使用:
[^,"]+(,[^,"]+)+
(注意:确保模式与结束双引号不匹配 - 否则模式可能会超出属性的结尾。)
哪会使您的查询:
SELECT *
FROM table1 f
WHERE REGEXP_LIKE(f.data, '"timeout_data":\s*"[^,"]+([^,"]+)+"')
AND ROWNUM<6;
注意:您不需要在过滤段之前或之后查找任何内容,也不需要转义双引号。