需要Oracle SQL substr / instr解决方案

时间:2013-01-24 18:30:49

标签: oracle substr

我需要帮助我正在尝试运行的SQL语句,我已经做了很多阅读和测试,但我无法得到正确的结果,因此我的请求在这里。

我正在尝试从已从两个源连接数据的列中提取数据,我想在&之前分离数据。加入后,加入是一个' - ' (带有空格的连字符),在此之前或之后可以有字母数字字符' - '这是我需要的数据。只是为了增加复杂性,一些行没有连接数据,即没有' - '当满足要求时,可以简单地提取整个列值并将其视为BB侧(参见下面的第一个BB示例)。

因此,当我结束时,我希望分离AA侧(在 - 之前)和BB侧(在 - 之后)允许单个BB情况。

查看数据可能会出现以下情况。

BB<br>
AA - BB<br>
AA-aa - BB<br>
AA - BB-bb-cc<br>
AA-aa - BB-bb-cc<br>

我可以让代码工作但不能始终如一地满足以上所有要求 - 你能否提出正确的代码,或者即使有更好的解决方案也不会影响SQL性能。

我一直在尝试AA方面的例子: -

工作:

select substr('AA - BB-bb', 0, instr('AA - BB-bb', ' - ', 1, 1)-1) AS A_NAME 
from DUAL;

失败(只获得AA,而不是AA-aa):

select substr('AA-aa - BB-bb', 0,instr('AA-aa - BB-bb', ' - ', 1, 1)-1) AS A_NAME
from DUAL;

我一直在尝试BB方面的例子: -

失败:

select SUBSTR('AA-aa - WHENEHEH', INSTR('AA-aa - WHENEHEH',' - ', -1, 1)+1, 100)
 B_NAME from dual;
谢谢,马克。

4 个答案:

答案 0 :(得分:1)

如果你的分离器确定gona是“爆炸两边的空间”

然后你可以使用CHR()函数。

从您的尝试

select substr('AA-aa - BB-bb', 0,instr('AA-aa - BB-bb', ' - ', 1, 1)-1) AS A_NAME
from DUAL;

使用类似的东西

select substr('AA-aa - BB-bb',0,instr('AA-aa - BB-bb',chr(32))-1) from dual; /* ASCII value for space is chr(32) /*

O / P

AA-AA

select substr('AA-aa - BB-bb',instr('AA-aa - BB-bb',chr(32))+2,10) from dual;

O / P

“ - BB”

答案 1 :(得分:0)

假设,如您的方案列表所示,模式&#39; - BB&#39;可以依赖,你可以用它来找到分裂。

WITH
DATA AS (
  SELECT 'BB' text FROM dual
  UNION ALL SELECT 'AA - BB' FROM dual
  UNION ALL SELECT 'AA-aa - BB' FROM dual
  UNION ALL SELECT 'AA - BB-bb-cc' FROM dual
  UNION ALL SELECT 'AA-aa - BB-bb-cc' FROM dual
  ),
break AS (
  SELECT text, instr(text, '- BB') breakpos  FROM DATA
)
SELECT
  text,
  CASE WHEN breakpos = 0 THEN NULL ELSE substr( text, 1, breakpos-1 ) END aa_side,
  case when breakpos = 0 then text else substr( text, breakpos+2) end bb_side
FROM break
;

答案 2 :(得分:0)

单个值的条件显示在第二列而不是第一列有点奇怪,但这应该做你需要的其他一切:

with testdata as (
select 'BB'  as input_col, 1 as row_num from dual
union
select 'AA - BB', 2 from dual
union
select 'AA-aa - BB',3 from dual
)
select testdata.row_num,
case when (regexp_instr(testdata.input_col,'(\ -\ )') > 0) then
  regexp_replace(testdata.input_col, '(.*)(\ -\ )(.*)$', '\1')
else null
end output_col1,
regexp_replace(testdata.input_col, '(.*)(\ -\ )(.*)$', '\3') as output_col2
from testdata
order by testdata.row_num;

编辑:我修改了上面的内容以添加案例检查。我承认通过regexp_replace本身可能有一种更有说服力的方法,但这也有效。

答案 3 :(得分:0)

我觉得这些东西对你有用。 (我希望我明白你的要求) 我用你提到的所有例子尝试了查询,但效果很好。

SELECT REGEXP_SUBSTR ('AA-aa - BB-bb-cc',
                  '[^ - ]+')
      "Right Side",
   SUBSTR ('AA-aa - BB-bb-cc',
             INSTR ('AA-aa - BB-bb-cc',
                    ' - ')
           + 2)
      "Left Side"
  FROM DUAL;

这个适用于除BB之外的所有内容,作为解决方法,您可以检查分隔符是否存在,如果不存在,您可以将整个值用于右侧。

SELECT    SUBSTR ('AA aa - BB',0,
           INSTR ('AA aa - BB',
                ' - ')
          )
    "Right Side",
SUBSTR('AA aa - BB',INSTR('AA aa - BB',
                  ' - ')+2)
      "Left Side"
 FROM DUAL;