在oracle中要求一个分割函数

时间:2018-08-28 09:22:28

标签: sql oracle plsql

现在有一个像这样的字符串:
    789 + 456-239

我想要这样的列表:

sign | num
+      789
+      456
-      239

2 个答案:

答案 0 :(得分:5)

这可能是一种使用常用的拆分字符串方法的方法,该方法仅适应您处理标牌的需要。

-- test case
with yourString(str) as 
        (
        select '+789+456-239 ' str
        from dual
        )
-- query
SELECT regexp_substr(str, '[+-]', 1, level) sign,
       regexp_substr(str, '[^+-]+', 1, level) num
  FROM ( select case                                  
                  when substr(str, 1, 1) in ('+','-') then str
                  -- I add a plus sign if the first char of the string is not a sign
                  else '+' || str 
                end as str
         from yourString
       )
CONNECT BY regexp_instr(str, '[+-]', 1, level ) > 0

这给出了:

SIGN           NUM
-------------- --------------
+              789
+              456
-              239

在这里,我假设如果在此字符串的开头没有给出任何符号,则第一个符号将为+

如果需要处理多个字符串,则需要在表中标识一个ID,CONNECT BY会变得更加复杂:

-- test case
with yourString(id, str) as 
        (
        select 1, '+789+456-239' from dual union all
        select 2, '789+456-239'  from dual union all
        select 3, '-789+456-239' from dual
        )
-- query
SELECT id,
       regexp_substr(str, '[+-]', 1, level) sign,
       regexp_substr(str, '[^+-]+', 1, level) num
  FROM ( select id,
                case                                  
                  when substr(str, 1, 1) in ('+','-') then str
                  -- I add a plus sign if the first char of the string is not a sign
                  else '+' || str 
                end as str
         from yourString
       )
CONNECT BY regexp_instr(str, '[+-]', 1, level ) > 0
  and prior id = id
  and prior sys_guid() is not null 

结果:

       ID SIGN  NUM
---------- ----- --------------------------------------------
         1 +     789
         1 +     456
         1 -     239
         2 +     789
         2 +     456
         2 -     239
         3 -     789
         3 +     456
         3 -     239

答案 1 :(得分:4)

这是一种不使用正则表达式并且可以处理多个输入行的方法:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( id, list ) AS
  SELECT 1, '789+456-239' FROM DUAL UNION ALL
  SELECT 2, '-123' FROM DUAL UNION ALL
  SELECT 3, '+456' FROM DUAL UNION ALL
  SELECT 4, '789' FROM DUAL;

查询1

WITH bounds ( id, list, start_pos, end_pos, lvl ) AS (
  SELECT id,
         list,
         1,
         CASE 
         WHEN INSTR( list, '+', 2 ) = 0 THEN INSTR( list, '-', 2 )
         WHEN INSTR( list, '-', 2 ) = 0 THEN INSTR( list, '+', 2 )
         ELSE LEAST( INSTR( list, '+', 2 ), INSTR( list, '-', 2 ) )
         END,
         1
  FROM   table_name
UNION ALL
  SELECT id,
         list,
         end_pos,
         CASE 
         WHEN INSTR( list, '+', end_pos + 1 ) = 0 THEN INSTR( list, '-', end_pos + 1 )
         WHEN INSTR( list, '-', end_pos + 1 ) = 0 THEN INSTR( list, '+', end_pos + 1 )
         ELSE LEAST( INSTR( list, '+', end_pos + 1 ), INSTR( list, '-', end_pos + 1 ) )
         END,
         lvl + 1
  FROM   bounds
  WHERE  end_pos > 0
)
SELECT id,
       DECODE( SUBSTR( list, start_pos, 1 ), '-', '-', '+' ) AS sign,
       SUBSTR(
         list,
         start_pos + DECODE( SUBSTR( list, start_pos, 1 ), '-', 1, '+', 1, 0 ),
         DECODE( end_pos, 0, LENGTH( list ) + 1, end_pos ) - start_pos - DECODE( SUBSTR( list, start_pos, 1 ), '-', 1, '+', 1, 0 )
       ) AS item,
      lvl
FROM   bounds
ORDER BY id, lvl

Results

| ID | SIGN | ITEM | LVL |
|----|------|------|-----|
|  1 |    + |  789 |   1 |
|  1 |    + |  456 |   2 |
|  1 |    - |  239 |   3 |
|  2 |    - |  123 |   1 |
|  3 |    + |  456 |   1 |
|  4 |    + |  789 |   1 |