如何将一串连接值拆分为特定列

时间:2015-11-08 04:33:04

标签: sql json oracle parsing

我们的数据库将多天的小时数存储为单个字符串(格式为JSON,见下文)。我需要提取任何一天的小时数。问题是JSON没有保证订单中的日期。

我用这种方式尝试substrinstr

SUBSTR(hours_xltd,
       INSTR(hours_xltd,'"MONDAY"', 1, 1)+1,
       INSTR(hours_xltd,',',1,2) - INSTR(hours_xltd,',',1,1)-1) as Monday

给了我MONDAY":"0800-1800","F,但我需要的是:

Monday
0800-1800

Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday我需要同样的东西。这是所需的输出(每天在其自己的列上,在我的示例中由管道表示);

   monday |   tuesday | wednesday |  thursday |    friday |  saturday |    sunday
----------------------------------------------------------------------------------
0800-1800 | 0800-1800 | 0800-1800 | 0800-1800 | 0800-1800 | 0800-1800 | 0800-1800

示例数据:

{
 "default": {
    "standard_hours": {
       "TUESDAY":"0800-1800",
       "SATURDAY":"0800-1400",
       "WEDNESDAY":"0800-1800",
       "THURSDAY":"0800-1800",
       "SUNDAY":"",
       "MONDAY":"0800-1800",
       "FRIDAY":"0800-1800"}
 }
}        

{ 
 "default": {
    "standard_hours": {
       "MONDAY":"0800-1800",
       "TUESDAY":"0800-1800",
       "WEDNESDAY":"0800-1800",
       "THURSDAY":"0800-1800",
       "FRIDAY":"0800-1800",
       "SATURDAY":"0800-1800",
       "SUNDAY":"0800-1800"}
  }
}

请帮我查看代码?我似乎无法解决这个问题。

1 个答案:

答案 0 :(得分:0)

让我们跳过一个关于以非结构化格式(如JSON)存储结构化数据并将其转移到解决方案的错误想法的咆哮。

我们可以使用正则表达式提取日期名称和小时。我们知道using regex in production code is a bad thing,所以当我们需要它时,最好尽可能保持清晰。

第一个公用表表达式提取DAY:HOUR字符串并将它们展开到结果集中(这个字符串拆分技巧有几种变体)。第二个CTE将DAY和HOUR字符串分开。主查询使用聚合来旋转行。

with std as ( select id
                     , regexp_substr(substr(json_str,31), '[^,]+', 1, level) as day_str
              from t23
              connect by level <= 7 )
     , hrs as ( select distinct id
                       , regexp_substr(day_str, '([A-Z]+)') as d_str
                       , regexp_substr(day_str, '([0-9\-]+)') as h_str
                 from std )
select id
       , max(case when d_str = 'MONDAY' then h_str end) as monday
       , max(case when d_str = 'TUESDAY' then h_str end) as tuesday
       , max(case when d_str = 'WEDNESDAY' then h_str end) as wednesday
       , max(case when d_str = 'THURSDAY' then h_str end) as thursday
       , max(case when d_str = 'FRIDAY' then h_str end) as friday
       , max(case when d_str = 'SATURDAY' then h_str end) as saturday
       , max(case when d_str = 'SUNDAY' then h_str end) as sunday
from hrs
group by id
order by id
/

请注意,我需要一个ID列才能使pivotimg正常工作。

 18  ...
 19  order by id
 20  /

        ID MONDAY    TUESDAY   WEDNESDAY THURSDAY  FRIDAY    SATURDAY  SUNDAY
---------- --------- --------- --------- --------- --------- --------- ---------
         1 0800-1800 0800-1800 0800-1800 0800-1800 0800-1800 0800-1400
         2 0800-1800 0800-1800 0800-1800 0800-1800 0800-1800 0800-1800 0800-1800

SQL>